使用Pandas处理可变数量的列-Python


76

我有一个看起来像这样的数据集(最多5列-但可以更少)

1,2,3
1,2,3,4
1,2,3,4,5
1,2
1,2,3,4
....

我正在尝试使用pandas read_table将其读取到5列数据框中。我想读这篇,无需额外按摩。

如果我尝试

import pandas as pd
my_cols=['A','B','C','D','E']
my_df=pd.read_table(path,sep=',',header=None,names=my_cols)

我收到一个错误-“列名有5个字段,数据有3个字段”。

有什么方法可以让熊猫在读取数据时为缺少的列填写NaN?

Answers:


80

似乎可行的一种方法(至少在0.10.1和0.11.0.dev-fc8de6d中):

>>> !cat ragged.csv
1,2,3
1,2,3,4
1,2,3,4,5
1,2
1,2,3,4
>>> my_cols = ["A", "B", "C", "D", "E"]
>>> pd.read_csv("ragged.csv", names=my_cols, engine='python')
   A  B   C   D   E
0  1  2   3 NaN NaN
1  1  2   3   4 NaN
2  1  2   3   4   5
3  1  2 NaN NaN NaN
4  1  2   3   4 NaN

注意,这种方法要求您为所需的列命名。不像其他方法那样通用,但是在适用时效果很好。


2
谢谢!这行得通-engine ='python'似乎是关键。添加此属性将使read_table和read_csv都可以工作。
Jackie Shephard

2
对我来说这似乎很谨慎。添加github问题:github.com/pydata/pandas/issues/2981
Wes McKinney

1
对我来说,解决问题的names=my_cols地方my_cols至少是与最多字段的线一样长的地方。如果事先不知道最大字段数,则可以通过预先读取文件来动态提取, with open('my.csv') as f: num_cols = max(len(line.split(',')) for line in f); f.seek(0); df = pd.read_csv(f, names=range(num_cols)) 但不利的是该文件被读取了两次。
EliadL

pd.read_csv(file, names=my_cols)即使len(my_cols)小于一或多个行中的字段数,Pandas 0.23.4版也可以使用。多余的字段将被丢弃。
卡·阿梅里奥

使用pandas 0.25.3时,如果某列的长度超过my_cols,则会失败
Gena Kukartsev

15

我也很想知道这是否可行,从文档看来似乎并非如此。您可能要做的就是逐行读取文件,并将每次读取连接到一个DataFrame:

import pandas as pd

df = pd.DataFrame()

with open(filepath, 'r') as f:
    for line in f:
        df = pd.concat( [df, pd.DataFrame([tuple(line.strip().split(','))])], ignore_index=True )

我想它可以工作,但不是以最优雅的方式进行。


1

好。不知道这有多有效-但这就是我所做的。很想知道是否有更好的方法可以做到这一点。谢谢 !

from pandas import DataFrame

list_of_dicts=[]
labels=['A','B','C','D','E']
for line in file:
    line=line.rstrip('\n')
    list_of_dicts.append(dict(zip(labels,line.split(','))))
frame=DataFrame(list_of_dicts)
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.