2013-06-15 2 views
3

저는 파이썬으로 작업 중이며 텍스트 파일에 매트릭스가 저장되어 있습니다. 텍스트 파일 등의 형식으로 배열된다텍스트 파일에서 시장 매트릭스 형식으로

ROW_ID,
ROW_ID을 col_id
...
ROW_ID을 col_id,

ROW_ID 및 col_id이 정수인 col_id 그들은 0의 값을 취 n (row_id와 col_id에 대해 n을 알기 위해서는 먼저 전체 파일을 스캔해야합니다).

헤더가없고 row_ids와 col_ids가 파일에 여러 번 나타나지만 각 행 row_id, col_id 조합은 한 번 나타납니다. 각 조합 row_id, col_id에 대한 명시적인 값은 없습니다. 실제로 각 셀 값은 1입니다. 파일 크기는 거의 1 기가 바이트입니다.

불행히도 파일은 메모리에서 처리하기가 어렵습니다. 실제로 26622704 개 요소의 경우 2257205 row_ids 및 122905 col_ids입니다. 그래서 나는 그것을 다루는 더 나은 방법을 찾고있었습니다. 매트릭스 시장 형식은이를 처리 할 방법이 될 수 있습니다.

이 파일을 Python을 사용하여 시장 매트릭스 형식 (http://math.nist.gov/MatrixMarket/formats.html#mtx)의 파일로 변환하는 빠르고 효율적인 방법이 있습니까?

+1

각 논리 셀 값이 비어 있거나 1이므로이 매트릭스는 본질적으로 2D 비트 맵입니다. 파이썬은 어떤 크기의 정수 값도 지원하기 때문에 정수의 목록으로 메모리에 행렬을 저장하고 조회 및 몇 비트 조작으로 모든 셀의 값을 결정할 수 있습니다. 행 ID와 열 ID의 상한선은 무엇입니까? – martineau

+0

행의 상한은 2257205이고 열은 122905입니다. –

+0

크기가 너무 커서 메모리에 저장할 수없는 비트 맵을 나타내는 데 약 32GB가 필요합니다. 대신 바이너리 파일에 저장할 수 있습니다. 비트 [row] [col]에 너무 액세스하면 어떤 바이트에 비트가 들어 있는지 계산하고, 해당 파일 오프셋을 찾고, 1 바이트를 읽거나 쓰는 것이 필요합니다. 26622704 개 요소에 대해 파일 IO가 많을 수 있지만 실현 가능성이 있습니다. – martineau

답변

6

이러한 매트릭스를 처리하는 빠르고 효율적인 방법이 있습니다 : sparse matrices offered by SciPy을 사용합니다 (이것은 사실상 파이썬의 표준입니다). N 크기의 행렬

N 기준 :

from scipy.sparse import lil_matrix 

result = lil_matrix((N, N)) # In order to save memory, one may add: dtype=bool, or dtype=numpy.int8 

with open('matrix.csv') as input_file: 
    for line in input_file: 
     x, y = map(int, line.split(',', 1)) # The "1" is only here to speed the splitting up 
     result[x, y] = 1 

(또는 하나 개의 라인 대신 2 : result[map(int, line.split(',', 1))] = 1).

split()에 주어진 인수 1은 좌표를 파싱 할 때 속도를 높이기 위해 여기에 있습니다. 첫 번째 (및 유일한) 쉼표가있는 경우 Python이 줄의 구문 분석을 중지하도록 지시합니다. 1GB 파일을 읽는 중이므로 문제가 될 수 있습니다.

필요에 따라 SciPy에서 제공하는 the other six sparse matrix representations 중 하나가 더 적합 할 수 있습니다.

더 빠르고 더 많은 메모리를 필요로하는 배열의 경우 result = numpy.array(…) (NumPy 포함)을 대신 사용할 수 있습니다.

MatrixMarket MM 형식

+0

line.split (',', 1)은 좋은 아이디어입니다! 고맙습니다. 나는 실제로 처음에 lil_matrix에서 시도했지만, 빠르지 만, 곧 메모리 오류가 발생했습니다. 그래서 저는 csc_matrix를 사용 했습니다만, 그러한 데이터 형식으로 값을로드하는 것은 매우 느립니다. –

+0

행렬 요소가 변경되지 않고 0과 1로 유지되면 float 대신 boolean 또는 int를 저장하면 공간을 절약 할 수 있습니다. 그 효과에 대한 코드에 주석을 추가했습니다. – EOL

+0

이 문서는 또한'dok_matrix'를 권장합니다 : 시도해 보셨습니까? 일반적으로 여러 개의 희소 매트릭스 표현을 시도하고 가장 적합한 매트릭스 표현을 확인하는 것보다 더 나은 것을 볼 수 없습니다. – EOL

1

내가 뭔가를 놓친 거지 않는 한 ... 상기 치수 라인과 "행 안부 값"입니다. 이미 행과 열이 있고 모든 값이 1 인 경우 값을 추가하기 만하면됩니다.

은 단순히 좌표가 하나의 오프셋을 경우 작동해야 그

n=`wc -l file` 
echo "2257205 122905 $n" > file.mm 
cat file | sed -e 's/$/ 1/g' >> file.mm 

에로 sed를 사용하는 것이 더 쉬울 수 없다. 오프셋이 0 인 경우 각 좌표에 +1을 추가하고 좌표를 읽고 각각에 하나씩 추가하고 coordx, coordy, "1"을 인쇄해야합니다. Awk이나 Python에서 쉘로 할 수있는 일은 거의 없습니다.

Q & D 코드 (테스트되지 않은, 힌트, YMMV 당신이 어떤 값을 계산하는 사전 처리에 파일을 할 수 있습니다대로 생산) : 쉘에서

파이썬에서
echo "2257205 122905 $n" 
cat file | while read x,y ; do x=$((x+1)); y=$((y+1)); echo "$x $y 1" ; done 

, 더 이하 ...

f=open("file") 
lines=f.readlines() 
print 2257205, 122905, len(lines) 
for l in lines: 
    (x,y) = l.split(' ') 
    x = int(x) + 1 
    y = int(y) + 1 
    print x, y, 1 

또는 뭔가 빠졌습니까?

관련 문제