[解決済み] 巨大な .csv ファイルを読み込む
質問
現在、Python 2.7で.csvファイルから最大100万行、200列のデータを読み込もうとしています(ファイルの範囲は100mbから1.6gbまでです)。300,000行以下のファイルであれば(非常にゆっくりですが)できますが、それ以上になるとメモリエラーが発生します。私のコードは次のようなものです。
def getdata(filename, criteria):
data=[]
for criterion in criteria:
data.append(getstuff(filename, criteron))
return data
def getstuff(filename, criterion):
import csv
data=[]
with open(filename, "rb") as csvfile:
datareader=csv.reader(csvfile)
for row in datareader:
if row[3]=="column header":
data.append(row)
elif len(data)<2 and row[3]!=criterion:
pass
elif row[3]==criterion:
data.append(row)
else:
return data
getstuff関数にelse節があるのは、条件に合う要素がcsvファイルにまとめてリストアップされるので、それを過ぎたらループを抜けて時間短縮を図っているからです。
私の質問は
-
どうすれば、より大きなファイルでこれを動作させることができるでしょうか?
-
もっと速くする方法はないでしょうか?
私のコンピューターは 8gb の RAM を持ち、64 ビット Windows 7 を実行し、プロセッサは 3.40 GHz です (必要な情報が何なのか定かではありません)。
どのように解決するのですか?
すべての行をリストに読み込んで、そのリストを処理しています。 そんなことしないでください .
行を生成するときに処理します。最初にデータをフィルタリングする必要がある場合は、ジェネレータ関数を使用します。
import csv
def getstuff(filename, criterion):
with open(filename, "rb") as csvfile:
datareader = csv.reader(csvfile)
yield next(datareader) # yield the header row
count = 0
for row in datareader:
if row[3] == criterion:
yield row
count += 1
elif count:
# done when having read a consecutive series of rows
return
また、あなたのフィルタテストを簡略化しました。ロジックは同じですが、より簡潔になっています。
基準に一致する単一の行のシーケンスにマッチするだけなので、使用することもできます。
import csv
from itertools import dropwhile, takewhile
def getstuff(filename, criterion):
with open(filename, "rb") as csvfile:
datareader = csv.reader(csvfile)
yield next(datareader) # yield the header row
# first row, plus any subsequent rows that match, then stop
# reading altogether
# Python 2: use `for row in takewhile(...): yield row` instead
# instead of `yield from takewhile(...)`.
yield from takewhile(
lambda r: r[3] == criterion,
dropwhile(lambda r: r[3] != criterion, datareader))
return
をループさせることができます。
getstuff()
を直接ループすることができます。同じことを
getdata()
:
def getdata(filename, criteria):
for criterion in criteria:
for row in getstuff(filename, criterion):
yield row
では、直接
getdata()
を直接ループしてください。
for row in getdata(somefilename, sequence_of_criteria):
# process row
現在、あなたが持っているのは 一行 をメモリに保持するようになりました。
yield
は、ある関数を
ジェネレータ関数
を生成します。これは、ループを開始するまで何もしないことを意味します。
関連
-
[解決済み] builtins.TypeError: strでなければならない、bytesではない
-
[解決済み】SyntaxError: デフォルト以外の引数がデフォルトの引数に続く
-
[解決済み] あるJavaScriptファイルを他のJavaScriptファイルにインクルードするにはどうすればよいですか?
-
[解決済み] ファイルのコピー方法について教えてください。
-
[解決済み] Pythonでファイルやフォルダを削除する方法は?
-
[解決済み] なぜC++はPythonよりもstdinからの行の読み込みが遅いのですか?
-
[解決済み] ファイルへの追記はどのように行うのですか?
-
[解決済み] Gitで1つのファイルの作業コピーの変更を元に戻す?
-
[解決済み] MySQLのクエリ結果をCSV形式で出力するにはどうすればよいですか?
-
[解決済み] pandasのDataFrameをCSVファイルに書き出す
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Pythonコンテナのための組み込み汎用関数操作
-
Python LeNetネットワークの説明とpytorchでの実装
-
Python Pillow Image.save jpg画像圧縮問題
-
Python 入出力と高次代入の基礎知識
-
[解決済み] [Solved] sklearn error ValueError: 入力に NaN、infinity または dtype('float64') に対して大きすぎる値が含まれている。
-
[解決済み】Pythonスクリプトで「Expected 2D array, got 1D array instead: 」というエラーが発生?
-
[解決済み] TypeError: 'DataFrame' オブジェクトは呼び出し可能ではない
-
[解決済み】Flask ImportError: Flask という名前のモジュールがない
-
[解決済み] pandasを使った "大量データ "ワークフロー【終了しました
-
[解決済み] Python Pandas: CSVファイルの最初のn行だけを読み込むには?