从generator创建pandas DataFrame?

lg40wkob  于 2023-06-28  发布在  其他
关注(0)|答案(6)|浏览(152)

我创建了一个元组生成器,它从文件中提取信息,只过滤感兴趣的记录,并将其转换为生成器返回的元组。
我尝试创建一个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。

    • 更新:**

这不是读取文件的问题,我的元组生成器做得很好,它逐行扫描混合记录的文本压缩文件,并仅将所需的数据转换为正确的类型,然后以元组形式生成字段。一些数字,它扫描2111412记录在一个130MB的gzip文件,约6.5GB未压缩,在大约一分钟内,几乎没有内存使用。
Pandas 0.12不允许生成器,开发版本允许它,但将所有生成器放在列表中,然后转换为帧。这不是有效的,但它的东西,必须处理内部Pandas。与此同时,我必须考虑买一些更多的内存。

wfauudbj

wfauudbj1#

你当然可以**从0.19版本(可能更早)的元组生成器中构造pandas.DataFrame()。不要使用.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  ~
oyt4ldly

oyt4ldly2#

您不能使用0.12版本的pandas从生成器创建DataFrame。你可以更新自己到开发版本(从github获取并编译它-这在Windows上有点痛苦,但我更喜欢这个选项)。
或者你可以,既然你说你正在过滤这些行,首先过滤它们,把它们写到一个文件中,然后用read_csv或其他东西加载它们...
如果你想变得超级复杂,你可以创建一个类似object的文件,它将返回以下行:

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
yqkkidmi

yqkkidmi3#

要使它具有内存效率,请分块读取。类似这样的东西,使用上面的Viktor的Reader类。

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

5uzkadbs4#

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

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/row/rows

6jjcrrmo

6jjcrrmo5#

如果generator就像一个DataFrames的列表,你只需要创建一个新的DataFrame连接列表的元素:
result = pd.concat(list)
最近我也遇到了同样的问题。

am46iovg

am46iovg6#

根据ChatGPT,下面的代码应该可以完成这项工作。使用Pandas 1.1.5和Python 3.8进行测试

import pandas as pd

def my_generator():
    yield {'Name': 'John', 'Age': 30, 'City': 'New York'}
    yield {'Name': 'Jane', 'Age': 25, 'City': 'Chicago'}
    yield {'Name': 'Mike', 'Age': 35, 'City': 'San Francisco'}

# Create the DataFrame using the generator expression
df = pd.DataFrame(data=my_generator())

# Display the DataFrame
print(df)

相关问题