Pandasのread_csv関数でロード時に行をフィルタリングするにはどうすればよいですか?


94

パンダを使用してメモリにロードするCSVの行をフィルタリングするにはどうすればよいですか?これは、で見つけられるはずのオプションのようread_csvです。何か不足していますか?

例:タイムスタンプ列のあるCSVがあり、指定された定数より大きいタイムスタンプを持つ行のみをロードしたいとします。

回答:


163

CSVファイルがpandasオブジェクトに読み込まれる前に行をフィルターするオプションはありません。

ファイルをロードしてからを使用してフィルタリングするdf[df['field'] > constant]か、非常に大きなファイルがあり、メモリ不足が心配な場合は、イテレータを使用してファイルのチャンクを連結するときにフィルタを適用します。例:

import pandas as pd
iter_csv = pd.read_csv('file.csv', iterator=True, chunksize=1000)
df = pd.concat([chunk[chunk['field'] > constant] for chunk in iter_csv])

あなたは変えることができchunksize、使用可能なメモリに合うように。詳細はこちらをご覧ください。


以下のためのchunk['filed']>constant私は2つの定数値の間に挟むことができますか?例:constant1> chunk ['field']> constant2。または「範囲内」を使用できますか?
weefwefwqg3 2017

試してみる:chunk[(chunk['field'] > constant2)&(chunk['field']<constant1)]
ヨハネスワックス

これはありませ.locんか?chunk.loc[chunk['field'] > constant]
ビンセント

1
ブールマスクは、を使用しても使用しなくても使用できます.loc.loc2012年には存在していなかったと思います.locが、最近の使用はもう少し明示的だと思います。
マティジョン

8

のコンテキスト内でそれを行う簡単な方法は見つかりませんでしたread_csv。ただし、read_csvDataFrameを返します。これは、ブールベクトルで行を選択することでフィルターできますdf[bool_vec]

filtered = df[(df['timestamp'] > targettime)]

これは、列の値がtargettimeの値よりも大きいdfのすべての行を選択しています(dfはread_csv、少なくとも日付時刻列を含む、呼び出しの結果などの任意のDataFrameであると想定していますtimestamptimestamp同様の質問


1
よくわかりませんが、メモリ使用量が非常に多くなると思います。
Nathan

2

フィルターされた範囲が連続している場合(通常はタイム(スタンプ)フィルターの場合のように)、最も速い解決策は行の範囲をハードコーディングすることです。単純に組み合わせることskiprows=range(1, start_row)nrows=end_rowパラメータを設定します。その後、インポートには数秒かかりますが、承認されたソリューションには数分かかります。イニシャルでのいくつかの実験は、start_rowインポート時間の節約を考えると、それほど大きなコストではありません。を使用してヘッダー行を保持したことに注意してくださいrange(1,..)


-3

Linuxを使用している場合は、grepを使用できます。

# to import either on Python2 or Python3
import pandas as pd
from time import time # not needed just for timing
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO


def zgrep_data(f, string):
    '''grep multiple items f is filepath, string is what you are filtering for'''

    grep = 'grep' # change to zgrep for gzipped files
    print('{} for {} from {}'.format(grep,string,f))
    start_time = time()
    if string == '':
        out = subprocess.check_output([grep, string, f])
        grep_data = StringIO(out)
        data = pd.read_csv(grep_data, sep=',', header=0)

    else:
        # read only the first row to get the columns. May need to change depending on 
        # how the data is stored
        columns = pd.read_csv(f, sep=',', nrows=1, header=None).values.tolist()[0]    

        out = subprocess.check_output([grep, string, f])
        grep_data = StringIO(out)

        data = pd.read_csv(grep_data, sep=',', names=columns, header=None)

    print('{} finished for {} - {} seconds'.format(grep,f,time()-start_time))
    return data

1
いくつかの理由により、grepを使用することは非常に悪い選択です。1)遅い2)移植性がない3)パンダまたはpythonではない(Python内で正規表現を使用できる)これが私が回答を否定した理由
Ahmed Masud

あなたのソリューションはすべてのプラットフォームで機能するわけではなく、Grepも含まれています。これが反対票の理由です。
Roman Orac

-3

nrowsパラメータを指定できます。

import pandas as pd df = pd.read_csv('file.csv', nrows=100)

このコードはバージョン0.20.3で正常に動作します。


1
OPは、読み取る行数を制限しないようにフィルタリングする方法を尋ねています。これが私があなたの答えを否定した理由です。
Roman Orac
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.