我有一个包含已知列的输入文件,比方说两列Name
和Sex
。有时它有标题行Name,Sex
,有时它不会:
1.csv :
Name,Sex
John,M
Leslie,F
2.csv :
John,M
Leslie,F
事先了解列的标识,是否有一种很好的方法可以使用相同的read_csv
命令处理这两种情况?基本上,我想指定names=['Name', 'Sex']
,然后仅在标题出现时才推断header=0
。我能想出的最好的是:
1)在执行read_csv
之前读取文件的第一行,然后设置
适当的参数。
2)做df = pd.read_csv(input_file, names=['Name', 'Sex'])
,
然后检查零行是否与标题相同,如果
所以放弃它(然后可能必须重新编号行)。
但这对我来说似乎并不像用例那么不寻常。是否有一种内置的方法可以用read_csv
来实现这一点,我没有想过?
答案 0 :(得分:7)
使用新功能 - selection by callable:
cols = ['Name','Sex']
df = (pd.read_csv(filename, header=None, names=cols)
[lambda x: np.ones(len(x)).astype(bool)
if (x.iloc[0] != cols).all()
else np.concatenate([[False], np.ones(len(x)-1).astype(bool)])]
)
使用.query()方法:
df = (pd.read_csv(filename, header=None, names=cols)
.query('Name != "Name" and Sex != "Sex"'))
我不确定这是最优雅的方式,但这也应该有效:
df = pd.read_csv(filename, header=None, names=cols)
if (df.iloc[0] == cols).all():
df = df[1:].reset_index(drop=True)
答案 1 :(得分:0)
我想出了一种在不事先知道标题名称的情况下检测标题的方法:
if any(df.iloc[0].apply(lambda x: isinstance(x, str))):
df = df[1:].reset_index(drop=True)
通过稍微更改它,可以使用检测到的标题更新当前标题:
if any(df.iloc[0].apply(lambda x: isinstance(x, str))):
df = df[1:].reset_index(drop=True).rename(columns=df.iloc[0])
这可以轻松选择所需的行为:
update_header = True
if any(df.iloc[0].apply(lambda x: isinstance(x, str))):
new_header = df.iloc[0]
df = df[1:].reset_index(drop=True)
if update_header:
df.rename(columns=new_header, inplace=True)
优点:
缺点:
if any()
替换为要求所有元素均为字符串可能会有所帮助。