从生成器创建一个pandas DataFrame?

时间:2013-09-20 11:42:51

标签: python pandas

我创建了一个元组生成器,它从文件中提取信息,仅过滤感兴趣的记录并将其转换为生成器返回的元组。

我尝试从以下位置创建DataFrame:

import pandas as pd
df = pd.DataFrame.from_records(tuple_generator, columns = tuple_fields_name_list)

但抛出错误:

... 
C:\Anaconda\envs\py33\lib\site-packages\pandas\core\frame.py in from_records(cls, data, index, exclude, columns, coerce_float, nrows)
   1046                 values.append(row)
   1047                 i += 1
-> 1048                 if i >= nrows:
   1049                     break
   1050 

TypeError: unorderable types: int() >= NoneType()

我设法让它在列表中使用生成器,但使用两次内存:

df = pd.DataFrame.from_records(list(tuple_generator), columns = tuple_fields_name_list)

我想加载的文件很大,内存消耗很重要。最后一次尝试我的电脑花了两个小时试图增加虚拟内存:(

问题:任何人都知道直接从记录生成器创建DataFrame的方法,而不事先将其转换为列表吗?

注意:我在Windows上使用python 3.3和pandas 0.12和Anaconda。

更新

这不是读取文件的问题,我的元组生成器做得很好,它逐行扫描混合记录的文本压缩文件,只将所需数据转换为正确的类型,然后生成元组生成器中的字段形成。 一些数字,它扫描13013 gzip文件上的2111412条记录,大约6.5分钟未压缩,大约一分钟,并且使用的内存很少。

Pandas 0.12不允许生成器,dev版本允许它但将所有生成器放入列表然后转换为帧。这不是有效的,但它必须处理内部大熊猫。与此同时,我必须考虑购买更多的记忆。

5 个答案:

答案 0 :(得分:14)

您无法使用0.12版本的pandas从生成器创建DataFrame。你可以自己更新到开发版本(从github获取它并编译它 - 这在Windows上有点痛苦,但我更喜欢这个选项。)

或者您可以,因为您说过滤线,首先对它们进行过滤,将它们写入文件,然后使用read_csv或其他内容加载......

如果你想变得非常复杂,你可以创建一个像对象一样的文件来返回行:

def gen():
    lines = [
        'col1,col2\n',
        'foo,bar\n',
        'foo,baz\n',
        'bar,baz\n'
    ]
    for line in lines:
        yield line

class Reader(object):
    def __init__(self, g):
        self.g = g
    def read(self, n=0):
        try:
            return next(self.g)
        except StopIteration:
            return ''

然后使用read_csv

>>> pd.read_csv(Reader(gen()))
  col1 col2
0  foo  bar
1  foo  baz
2  bar  baz

答案 1 :(得分:10)

你肯定可以从元组生成器构造pandas.DataFrame(),从版本19开始(可能更早)。不要使用.from_records();只需使用构造函数,例如:

import pandas as pd
someGenerator = ( (x, chr(x)) for x in range(48,127) )
someDf = pd.DataFrame(someGenerator)

产地:

type(someDf) #pandas.core.frame.DataFrame

someDf.dtypes
#0     int64
#1    object
#dtype: object

someDf.tail(10)
#      0  1
#69  117  u
#70  118  v
#71  119  w
#72  120  x
#73  121  y
#74  122  z
#75  123  {
#76  124  |
#77  125  }
#78  126  ~

答案 2 :(得分:6)

要使其具有内存效率,请阅读块。这样的事情,使用上面的Viktor的Reader类。

df = pd.concat(list(pd.read_csv(Reader(gen()),chunksize=10000)),axis=1)

答案 3 :(得分:1)

您也可以使用类似(在2.7.5中测试的Python)

from itertools import izip

def dataframe_from_row_iterator(row_iterator, colnames):
    col_iterator = izip(*row_iterator)
    return pd.DataFrame({cn: cv for (cn, cv) in izip(colnames, col_iterator)})

您还可以对此进行调整以将行附加到DataFrame。

- 编辑,12月4日:最后一行中的s /行/行

答案 4 :(得分:0)

如果生成器就像DataFrames的列表一样,您只需要创建列表中新的DataFrame连接元素:

result = pd.concat(list)

最近我遇到了同样的问题。