pandas 中 csv 的条件行读取
conditional row read of csv in pandas
我有大型 CSV,其中我只对行的子集感兴趣。特别是,我想读入满足特定条件之前发生的所有行。
例如,如果 read_csv
将产生数据帧:
A B C
1 34 3.20 'b'
2 24 9.21 'b'
3 34 3.32 'c'
4 24 24.3 'c'
5 35 1.12 'a'
...
1e9 42 2.15 'd'
有什么方法可以读取 csv 中的所有行,直到 col B 超过 10。在上面的示例中,我想读入:
A B C
1 34 3.20 'b'
2 24 9.21 'b'
3 34 3.32 'c'
4 24 24.3 'c'
我知道如何在读入数据帧后将这些行扔掉,但此时我已经花费了所有计算来读入它们。我无权访问最后一行的索引在阅读 csv 之前(请不要 skipfooter)
您可以分块阅读 csv。由于在指定 chunksize
参数时 pd.read_csv
将 return 一个迭代器,因此您可以使用 itertools.takewhile
只读取所需数量的块,而无需读取整个文件。
import itertools as IT
import pandas as pd
chunksize = 10 ** 5
chunks = pd.read_csv(filename, chunksize=chunksize, header=None)
chunks = IT.takewhile(lambda chunk: chunk['B'].iloc[-1] < 10, chunks)
df = pd.concat(chunks)
mask = df['B'] < 10
df = df.loc[mask]
或者,为了避免必须使用 df.loc[mask]
从最后一个块中删除不需要的行,也许更清晰的解决方案是定义一个自定义生成器:
import itertools as IT
import pandas as pd
def valid(chunks):
for chunk in chunks:
mask = chunk['B'] < 10
if mask.all():
yield chunk
else:
yield chunk.loc[mask]
break
chunksize = 10 ** 5
chunks = pd.read_csv(filename, chunksize=chunksize, header=None)
df = pd.concat(valid(chunks))
我会选择这里描述的简单路线:
http://pandas.pydata.org/pandas-docs/stable/indexing.html#boolean-indexing
df[df['B'] > 10]
您可以使用内置的 csv
模块来计算适当的行号。然后使用 pd.read_csv
和 nrows
参数:
from io import StringIO
import pandas as pd
import csv, copy
mycsv = StringIO(""" A B C
34 3.20 'b'
24 9.21 'b'
34 3.32 'c'
24 24.3 'c'
35 1.12 'a'""")
mycsv2 = copy.copy(mycsv) # copying StringIO object [for demonstration purposes]
with mycsv as fin:
reader = csv.reader(fin, delimiter=' ', skipinitialspace=True)
header = next(reader)
counter = next(idx for idx, row in enumerate(reader) if float(row[1]) > 10)
df = pd.read_csv(mycsv2, delim_whitespace=True, nrows=counter+1)
print(df)
A B C
0 34 3.20 'b'
1 24 9.21 'b'
2 34 3.32 'c'
3 24 24.30 'c'
基于@joanwa 的回答:
df = (pd.read_csv("filename.csv")
[lambda x: x['B'] > 10])
来自 Wes McKinney 的 "Python for Data Analysis" 章节
在 "Advanced pandas":
我们不能引用 load_data 的结果,直到它被分配给临时变量 df。为了解决这个问题,assign 和许多其他 pandas 函数接受类似函数的参数,也称为可调用对象。
要显示可调用对象的运行情况,请考虑...
df = load_data()
df2 = df[df['col2'] < 0]
可以重写为:
df = (load_data()
[lambda x: x['col2'] < 0])
我有大型 CSV,其中我只对行的子集感兴趣。特别是,我想读入满足特定条件之前发生的所有行。
例如,如果 read_csv
将产生数据帧:
A B C
1 34 3.20 'b'
2 24 9.21 'b'
3 34 3.32 'c'
4 24 24.3 'c'
5 35 1.12 'a'
...
1e9 42 2.15 'd'
有什么方法可以读取 csv 中的所有行,直到 col B 超过 10。在上面的示例中,我想读入:
A B C
1 34 3.20 'b'
2 24 9.21 'b'
3 34 3.32 'c'
4 24 24.3 'c'
我知道如何在读入数据帧后将这些行扔掉,但此时我已经花费了所有计算来读入它们。我无权访问最后一行的索引在阅读 csv 之前(请不要 skipfooter)
您可以分块阅读 csv。由于在指定 chunksize
参数时 pd.read_csv
将 return 一个迭代器,因此您可以使用 itertools.takewhile
只读取所需数量的块,而无需读取整个文件。
import itertools as IT
import pandas as pd
chunksize = 10 ** 5
chunks = pd.read_csv(filename, chunksize=chunksize, header=None)
chunks = IT.takewhile(lambda chunk: chunk['B'].iloc[-1] < 10, chunks)
df = pd.concat(chunks)
mask = df['B'] < 10
df = df.loc[mask]
或者,为了避免必须使用 df.loc[mask]
从最后一个块中删除不需要的行,也许更清晰的解决方案是定义一个自定义生成器:
import itertools as IT
import pandas as pd
def valid(chunks):
for chunk in chunks:
mask = chunk['B'] < 10
if mask.all():
yield chunk
else:
yield chunk.loc[mask]
break
chunksize = 10 ** 5
chunks = pd.read_csv(filename, chunksize=chunksize, header=None)
df = pd.concat(valid(chunks))
我会选择这里描述的简单路线:
http://pandas.pydata.org/pandas-docs/stable/indexing.html#boolean-indexing
df[df['B'] > 10]
您可以使用内置的 csv
模块来计算适当的行号。然后使用 pd.read_csv
和 nrows
参数:
from io import StringIO
import pandas as pd
import csv, copy
mycsv = StringIO(""" A B C
34 3.20 'b'
24 9.21 'b'
34 3.32 'c'
24 24.3 'c'
35 1.12 'a'""")
mycsv2 = copy.copy(mycsv) # copying StringIO object [for demonstration purposes]
with mycsv as fin:
reader = csv.reader(fin, delimiter=' ', skipinitialspace=True)
header = next(reader)
counter = next(idx for idx, row in enumerate(reader) if float(row[1]) > 10)
df = pd.read_csv(mycsv2, delim_whitespace=True, nrows=counter+1)
print(df)
A B C
0 34 3.20 'b'
1 24 9.21 'b'
2 34 3.32 'c'
3 24 24.30 'c'
基于@joanwa 的回答:
df = (pd.read_csv("filename.csv")
[lambda x: x['B'] > 10])
来自 Wes McKinney 的 "Python for Data Analysis" 章节 在 "Advanced pandas":
我们不能引用 load_data 的结果,直到它被分配给临时变量 df。为了解决这个问题,assign 和许多其他 pandas 函数接受类似函数的参数,也称为可调用对象。
要显示可调用对象的运行情况,请考虑...
df = load_data()
df2 = df[df['col2'] < 0]
可以重写为:
df = (load_data()
[lambda x: x['col2'] < 0])