【问题标题】:How do I read a fixed width format text file in pandas?如何在 pandas 中读取固定宽度格式的文本文件?
【发布时间】:2012-03-15 14:08:31
【问题描述】:

我刚刚接触到 pandas,正在研究如何读取文件。该文件来自 WRDS 数据库,是自 1960 年代以来的 SP500 成分列表。我检查了文件,无论使用read_csv 导入它,我仍然无法正确显示数据。

df = read_csv('sp500-sb.txt')

df

<class 'pandas.core.frame.DataFrame'>
Int64Index: 1231 entries, 0 to 1230
Data columns: gvkeyx      from      thru     conm
                                        gvkey      co_conm
...(the column names)
dtypes: object(1)

上面的输出块是什么意思?任何事情都会有所帮助。

【问题讨论】:

  • 熊猫可能吃掉了你的数据?
  • 你能显示文件的前几行吗?

标签: python pandas fixed-width


【解决方案1】:

pandas.read_fwf() 被添加到 pandas 0.7.3 (April 2012) 以处理固定宽度的文件。

  1. API reference

  2. An example from other question

【讨论】:

    【解决方案2】:

    Wes 在电子邮件中回复了我。干杯。

    这是一个固定宽度格式的文件(不以逗号或制表符分隔为 通常)。我意识到熊猫没有像固定宽度的阅读器 R 确实如此,尽管可以很容易地塑造它。我会看看我能做什么 做。同时,如果您可以以其他格式导出数据(例如 csv——真正的逗号分隔)你将能够使用 read_csv 读取它。一世 怀疑有一些 unix 魔法,您可以将 FWF 文件转换为 CSV 文件。

    我建议您关注 github 上的问题,因为您的电子邮件即将发送 从我的收件箱中消失 :)

    https://github.com/pydata/pandas/issues/920

    最好, 韦斯

    【讨论】:

    【解决方案3】:

    你说的显示是什么意思? df['gvkey']不给你gvkey列的数据吗?

    如果您所做的是将整个数据框打印到控制台,请查看df.to_string(),但如果您的列太多,则很难阅读。如果列太多,Pandas 默认不会打印整个内容:

    import pandas
    import numpy 
    
    df1 = pandas.DataFrame(numpy.random.randn(10, 3), columns=['col%d' % d for d in range(3)] )
    df2 = pandas.DataFrame(numpy.random.randn(10, 30), columns=['col%d' % d for d in range(30)] )
    
    print df1   # <--- substitute by df2 to see the difference
    print
    print df1['col1']
    print
    print df1.to_string()
    

    【讨论】:

    • 感谢 TR。我的数据文件是固定宽度格式...目前不支持。 Wes 已慷慨地添加到源伪造 pandas 问题列表中。
    • 您还可以访问 WRDS 吗?您应该可以选择以 csv 格式输出文件。
    【解决方案4】:

    用户,如果你现在需要处理固定格式,你可以使用类似下面的东西:

    def fixed_width_to_items(filename, fields, first_column_is_index=False, ignore_first_rows=0):
        reader = open(filename, 'r')
        # skip first rows 
        for i in xrange(ignore_first_rows):
            reader.next()
        if first_column_is_index:
            index = slice(0, fields[1])
            fields = [slice(*x) for x  in zip(fields[1:-1], fields[2:])]
            return ((line[index], [line[x].strip() for x in fields]) for line in reader)
        else:
            fields = [slice(*x) for x  in zip(fields[:-1], fields[1:])]
            return ((i, [line[x].strip() for x in fields]) for i,line in enumerate(reader)) 
    

    这是一个测试程序:

    import pandas
    import numpy
    import tempfile
    
    # create a data frame
    df = pandas.DataFrame(numpy.random.randn(100, 5))
    file_ = tempfile.NamedTemporaryFile(delete=True)
    file_.write(df.to_string())
    file_.flush()
    
    # specify fields
    fields = [0, 3, 12, 22, 32, 42, 52]
    df2 = pandas.DataFrame.from_items( fixed_width_to_items(file_.name, fields, first_column_is_index=True, ignore_first_rows=1) ).T
    
    # need to specify the datatypes, otherwise everything is a string
    df2 = pandas.DataFrame(df2, dtype=float)
    df2.index = [int(x) for x in df2.index]
    
    # check
    assert (df - df2).abs().max().max() < 1E-6
    

    如果您现在需要它,这应该可以解决问题,但请记住,上面的函数非常简单,特别是它对数据类型没有任何作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-01
      • 2016-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多