【问题标题】:Pandas csv reader creates NaN indexPandas csv 阅读器创建 NaN 索引
【发布时间】:2018-10-12 10:16:43
【问题描述】:

我有一个 CSV 文件,其内容如下:

A: 12, B: 14
A:  1, B:  4
A:  2, B:  1
A: 21, B: 41

我可以用正则表达式分隔列:

import pandas as pd

df = pd.read_csv("test.csv", sep = ":\s*|,\s*", names = ["dummy1", "A", "dummy2", "B"], engine = "python")
print(df)

输出

  dummy1   A dummy2   B
0      A  12      B  14
1      A   1      B   4
2      A   2      B   1
3      A  21      B  41

为了防止创建无用的列,我尝试了以下策略:

import pandas as pd

df1 = pd.read_csv("test.csv", sep = "A:\s*|,\s*B:\s*", names = ["A", "B"], engine = "python")
print(df1)

但现在索引只包含NaN 值:

      A   B
NaN  12  14
NaN   1   4
NaN   2   1
NaN  21  41

为什么会发生这种情况以及如何预防?

【问题讨论】:

    标签: python python-3.x pandas csv


    【解决方案1】:

    pandas.read_csv 函数接受 index_col 参数,该参数指示 DataFrame 的行标签(索引)。您需要使用 int 或索引序列设置 this 参数,因为默认情况下它是 None。

    index_col : int or sequence or False, default None

    用作 DataFrame 的行标签的列。如果给定一个序列,则使用 MultiIndex。如果您的文件格式错误,每行末尾都有分隔符,您可能会考虑使用index_col=False 强制 pandas 不使用第一列作为索引(行名)

    如果这仍然不起作用,您可以放弃使用delimiter,只需对两列都使用转换器函数将数字与字母字符分开:

    func = lambda x: x.split(':')[-1]
    df1 = pd.read_csv("test.csv",
                      names = ["A", "B"],
                      engine = "python",
                      converters={'A': func,
                                  'B': func})
    

    输出:

         A    B
    0   12   14
    1    1    4
    2    2    1
    3   21   41
    

    【讨论】:

    • index_col = False 有一个有趣的效果。现在索引符合预期,但A 包含NaN 值和B 值A。就好像我的第二个版本创建了一个仅包含 NaN 值的附加列零。虽然我不明白为什么会发生这种情况。
    • @Mr.T 听起来是因为省略了那些列名或分隔符。
    • 可能是因为 csv 导入期间的分隔符总是将一行分成两部分,但是因为该行以第一个分隔符开头,它创建了一个 NaN 值列而不是简单地忽略它?所以基本上,我的策略从分隔符开始是愚蠢的?
    • @Mr.T 是的,这绝对是可能的,但分隔符不一定分成两部分。正如 cmets 中提到的,当分隔符的长度超过一个时,Pandas 会将它们视为正则表达式。我认为在这种情况下只能使用空格作为分隔符。
    • 但这是我的策略之一,它创建了比需要更多的列。如果第二个策略也像第一个策略一样创建不需要的列,我可能会退回到usecols = [1, 3]。
    【解决方案2】:

    看起来,这是分隔符的预期行为。正则表达式/非正则表达式分隔符和 python/c 引擎是相同的,我们可以从以下示例中看到:

    A 12 13 A 14 A
    A 22 23 A 24 A
    A 32 33 A 34 A
    

    脚本

    df2 = pd.read_csv("test1.csv", sep = "A", index_col = False, header = None, engine = "c")
    print(df2)
    

    在开头和结尾生成一列NaN 值:

        0        1   2   3
    0 NaN   12 13   14 NaN
    1 NaN   22 23   24 NaN
    2 NaN   32 33   34 NaN
    

    这有点令人惊讶,我原以为引擎会忽略不存在的值。好吧,我们现在都是代码的奴隶。
    最简单的方法似乎是在第一个示例中为csv reader 参数usecols 提供便利:

    df = pd.read_csv("test.csv", sep = ":\s*|,\s*", names = ["A", "B"], usecols = [1, 3],  engine = "python")
    print(df)
    
        A   B
    0  12  14
    1   1   4
    2   2   1
    3  21  41
    

    这会降低脚本的灵活性,因为您必须提前了解数据结构。仍然欢迎提出建议。

    【讨论】:

      猜你喜欢
      • 2014-05-04
      • 2019-08-22
      • 2018-06-05
      • 1970-01-01
      • 1970-01-01
      • 2013-03-06
      • 1970-01-01
      • 2012-12-20
      • 1970-01-01
      相关资源
      最近更新 更多