我创建了一个元组生成器,它从文件中提取信息,仅过滤感兴趣的记录并将其转换为生成器返回的元组。
我尝试从以下位置创建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版本允许它但将所有生成器放入列表然后转换为帧。这不是有效的,但它必须处理内部大熊猫。与此同时,我必须考虑购买更多的记忆。
答案 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)
最近我遇到了同样的问题。