読み込んで辞書を作成する必要がある大きなファイルがあります。私はこれをできるだけ速くしたいと思っています。しかし、Python での私のコードは遅すぎます。問題を示す最小限の例を次に示します。
最初にいくつかの偽のデータを作成します
paste <(seq 20000000) <(seq 2 20000001) > largefile.txt
これは、それを読み込んで辞書を作成するための最小限の Python コードです。
import sys
from collections import defaultdict
fin = open(sys.argv[1])
dict = defaultdict(list)
for line in fin:
parts = line.split()
dict[parts[0]].append(parts[1])
タイミング:
time ./read.py largefile.txt
real 0m55.746s
ただし、次のように I/O バウンドではありません。
time cut -f1 largefile.txt > /dev/null
real 0m1.702s
行をコメントアウトすると、数秒dict
かかり9
ます。ほぼすべての時間を に費やされているようdict[parts[0]].append(parts[1])
です。
これをスピードアップする方法はありますか?それが大きな違いを生むのであれば、私は cython や C を使ってもかまいません。それともパンダがここで助けてくれますか?
サイズが 10000000 行のファイルのプロファイル出力を次に示します。
python -m cProfile read.py test.data 20000009 function calls in 42.494 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.000 0.000 bisect.py:1(<module>)
1 0.000 0.000 0.001 0.001 collections.py:1(<module>)
1 0.000 0.000 0.000 0.000 collections.py:25(OrderedDict)
1 0.000 0.000 0.000 0.000 collections.py:386(Counter)
1 0.000 0.000 0.000 0.000 heapq.py:31(<module>)
1 0.000 0.000 0.000 0.000 keyword.py:11(<module>)
1 30.727 30.727 42.494 42.494 read.py:2(<module>)
10000000 4.855 0.000 4.855 0.000 {method 'append' of 'list' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
10000000 6.912 0.000 6.912 0.000 {method 'split of 'str' objects}
1 0.000 0.000 0.000 0.000 {open}
アップデート。 parts[1] は整数で、parts[0] は短い固定長の文字列であると想定できます。
キーごとに 1 つの値しか取得できないため、私の偽のデータはあまり良くありません。これがより良いバージョンです。
perl -E 'say int rand 1e7, $", int rand 1e4 for 1 .. 1e7' > largefile.txt
ここで行う唯一の操作は、キーにクエリを実行して、それに関連付けられた値のリストを返すことです。