如何在Pandas read_csv函数的负载中过滤行?


94

如何使用熊猫过滤CSV的哪些行要加载到内存中?这似乎是应该在中找到的一种选择read_csv。我想念什么吗?

示例:我们有一个带时间戳列的CSV,我们只想加载时间戳大于给定常量的行。

Answers:


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

试试:chunk[(chunk['field'] > constant2)&(chunk['field']<constant1)]
Johannes Wachs

这是缺少的.loc吗?chunk.loc[chunk['field'] > constant]
文森特

1
可以使用带或不带布尔型掩码.loc。我认为.loc早在2012年就不存在,但我想这些天的使用.loc更为明确。
马蒂·约翰

8

在的上下文中,我没有找到直接的方法read_csv。但是,read_csv返回一个DataFrame,可以通过按布尔向量选择行来对其进行过滤df[bool_vec]

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

这将选择df中的所有行(假设df是任何DataFrame,例如read_csv调用的结果,至少包含datetime列timestamp),因此该timestamp列中的值大于targettime的值。类似的问题


1
我对此不太确定,但我觉得这会占用大量内存。
弥敦道

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。这就是投票否决的原因。
罗马奥拉克

-3

您可以指定nrows参数。

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

此代码在0.20.3版中效果很好。


1
OP正在询问如何过滤而不限制读取的行数。这就是为什么我拒绝您的回答。
罗马奥拉克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.