【问题标题】:Pandas read_csv without knowing whether header is presentPandas read_csv 不知道是否存在标头
【发布时间】:2016-11-16 13:28:57
【问题描述】:

我有一个包含已知列的输入文件,假设有两列 NameSex。有时它有标题行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 的内置方法?

【问题讨论】:

    标签: python csv pandas


    【解决方案1】:

    使用新功能 - 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)
    

    【讨论】:

    • 感谢所有选项!最后一个版本对我来说仍然看起来最干净,所以我想我会使用这种方法。如果没有其他问题,我将暂时保留问题并在几天后接受。
    • 感谢您的帮助,对我来说,我必须在 read_csv 中设置 index_col=False 才能让第一行在有标题时对齐。
    【解决方案2】:

    我想出了一种在不知道标题名称的情况下检测标题的方法:

    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() 以要求所有元素都是字符串可能会有所帮助,除非数据还包含整行字符串。

    【讨论】:

      猜你喜欢
      • 2019-05-18
      • 2018-01-06
      • 1970-01-01
      • 1970-01-01
      • 2023-02-11
      • 2019-07-22
      • 2017-05-15
      • 2015-06-07
      • 2019-01-26
      相关资源
      最近更新 更多