2010-11-26 3 views
6

Mathematica에서 느린 로딩을 구현해야합니다. 나는 600 MB CSV 텍스트 파일을 처리해야합니다. 이 파일은 중복 기록이 많이 포함되어 메모리에 그들 모두를로드하는 그래서 그 대신큰 텍스트 파일 처리

1;0;0;13;6 
1;0;0;13;6 
.......... 
2;0;0;13;6 
2;0;0;13;6 
.......... 
etc. 

를, 나는 기록이 레코드가 파일에 발생 된 횟수를 포함하는 목록을 만들려면 :

{{10000,{1,0,0,13,6}}, {20000,{2,0,0,13,6}}, ...} 

가져 오기 기능으로 할 수있는 방법을 찾을 수 없습니다. myProcessingFunction 한 번에 하나 개의 레코드를 가지고 데이터 집합을 생성합니다 어디

Import["my_file.csv", "CSV", myProcessingFunction] 

처럼 뭔가를 찾고 있어요. Import 나 다른 Mathematica 함수로 이것을 할 수 있습니까?

+0

모르는 경우가 있는데이를 런 길이 인코딩이라고합니다. Mathematica 알고리즘을 구현하기위한 몇 가지 깔끔한 알고리즘이 있습니다. –

+2

@Tim Kemp : 알고리즘을 실행하기 전에 데이터를 먼저로드해야합니다. 데이터의 크기로 인해 데이터가 한 번에로드되지 않습니다. 내 질문은 레코드를 그룹화하는 방법보다는 한 줄씩 데이터를로드하는 방법에 관한 것입니다. 또한 RLE 알고리즘은 일련의 레코드를 보존합니다. 나는 이것을 필요로하지 않는다. 나는 카운트 만 필요로한다. 예를 들어, RLE가 3A, 4B, 4A가 된 후에 AAABBBBAAAA. 7A, 4B가 필요해. – Max

답변

2

만약 제가라면 sortuniq 유닉스를 사용하여이 작업을 수행 할 것입니다. 그러나 Mathematica에 관해서는 물어 보았습니다. 필자는 ReadList []를 사용하여 줄 블록을 읽고 아래쪽 값을 정의하여 고유 한 문자열 이전에 본 개수를 추적합니다.

(* Create some test data *) 
Export["/tmp/test.txt", Flatten[{Range[1000], Range[1000]}], "Lines"]; 

countUniqueLines[file_String, blockSize_Integer] := Module[{stream, map, block, keys, out}, 
    map[_]:=0; 
    stream = OpenRead[file]; 
    CheckAbort[While[(block=ReadList[stream, String, blockSize])=!={}, 
     (map[#]=map[#]+1)& /@ block;];, Close[stream];Clear[map]]; 
    Close[stream]; 
    keys = Cases[DownValues[map][[All, 1, 1, 1]], _String]; 
    out = {#, map[#]}& /@ keys; 
    Clear[map]; 
    out 
] 

countUniqueLines["/tmp/test.txt", 500] 


(* Alternative implementation if you have a little more memory *) 
Tally[Import["/tmp/test.txt", "Lines"]] 
+0

+1, 확실히 접근 방법입니다. 세개. while 루프는'CheckAbort'에 래핑 될 필요가 있습니다. 그렇지 않으면 스트림은 열려있을 때 남아있게됩니다. 이것은 대용량 파일을 다룰 때 매우 중요합니다. 둘째, 세미콜론은'WordSeparators'에 포함되어야합니다. 그렇지 않으면 세미콜론이 CSV 파일로 많은 오류를 생성합니다. 마지막으로, 600 mb 파일로 얼마나 잘 동작합니까? – rcollyer

+0

@rcollyer, CheckAbort 처리를 추가했습니다. 이 함수는 행만 처리합니다. 일부 메모리를 절약하는 필드를 구분하지 않습니다.그것은 ";"을 깨기 위해 ReadList를 변경하는 것처럼 간단해야합니다. –

2

나는 Read[] 기능을 원한다고 생각합니다.

2

아마도 이것을하기위한 Mathematica보다 나은 대안이있을 것입니다.

작은 awk 스크립트는 :

{a[$0]++} 
END { ... print loop ... } 

는 반복 기록을 축적합니다. 물론 개별 레코드의 수에 따라 오버플로가 발생할 수 있습니다.

파일을 먼저 정렬하면 계산이 오버플로되지 않습니다. awk에서 non-overflows 프로그램은 다음과 유사 할 수 있습니다.

BEGIN{ p =""; i=0} 

{if (($0 != p) && (i != 0)) {print $0,i ; p =$0; i=0; next}} 

{i++; p = $0} 

아마도 Perl은 더 좋지만 저는 구식입니다.

HTH!

+2

물론 Mathematica에서 awk 나 perl을 호출 할 수 있습니다. –

0

나는 MySQL은 같은 데이터베이스 시스템에 먼저로드 고려하는 당신을 추천 할 것입니다 그리고 당신은 DatabaseLink를 사용하여 티카에서 액세스 할 수 있습니다.