类型错误:第一个参数必须是pandas对象的可迭代对象,您传递了一种“ DataFrame”类型的对象。

71

我有一个很大的数据框,我想把它分开,然后在 concat 它们。我使用

df2 = pd.read_csv('et_users.csv', header=None, names=names2, chunksize=100000)
for chunk in df2:
    chunk['ID'] = chunk.ID.map(rep.set_index('member_id')['panel_mm_id'])

df2 = pd.concat(chunk, ignore_index=True)

但它返回了一个错误。

TypeError: first argument must be an iterable of pandas objects, you passed an object of type "DataFrame"

我该如何修复这个问题?


错误很明显,但即使您传递了数据框列表,也会在循环中覆盖ID列:for chunk in df2: chunk['ID'] = chunk.ID.map(rep.set_index('member_id')['panel_mm_id']) 您的意图是什么?您想创建一些新的df吗?您应该将每个块附加到某个列表中,然后调用concat - EdChum
@EdChum 我尝试从其他数据框中替换chunk['ID']中的值。接下来,我应该使用chunk = chunk.dropna(),然后我应该连接块。 - Petr Petrov
5个回答

184

我遇到了相同的问题,后来才意识到我们必须将(多个!)数据框作为列表传递给第一个参数,而不是作为多个参数传递!

参考资料:https://pandas.pydata.org/pandas-docs/stable/generated/pandas.concat.html

a = pd.DataFrame()
b = pd.DataFrame()
c = pd.concat(a,b) # errors out:
TypeError: first argument must be an iterable of pandas objects, you passed an object of type "DataFrame"

c = pd.concat([a,b]) # works.
如果处理操作不需要所有数据都存在,那么就没有理由将所有块保存到外部数组中并且只在拆块循环结束后一次性处理所有内容:这违反了拆块的整个目的。我们使用拆块是因为我们想要在每个块上进行处理,并释放内存以供下一个块使用。
关于 OP 的代码,他们需要创建另一个空的数据帧并将块串联到其中。
df3 = pd.DataFrame() # create empty df for collecting chunks
df2 = pd.read_csv('et_users.csv', header=None, names=names2, chunksize=100000)
for chunk in df2:
    chunk['ID'] = chunk.ID.map(rep.set_index('member_id')['panel_mm_id'])
    df3 = pd.concat([df3,chunk], ignore_index=True)

print(df3)

然而,我想再次强调,块处理技术的发明正是为了避免将整个 CSV 的所有行构建成单个 DataFrame,因为这会在处理大型 CSV 时导致内存不足错误。我们不希望仅仅将错误从 pd.read_csv() 移到 pd.concat()。我们需要找到方法来在块循环中完成大部分数据处理任务。在我的用例中,我使用 df 查询消除了大部分行,并只连接了较少所需的行,因此最终的 df 比原始 csv 小得多。


16

我理解您想要以下内容:

df2 = pd.read_csv('et_users.csv', header=None, names=names2, chunksize=100000)
chunks=[]
for chunk in df2:
    chunk['ID'] = chunk.ID.map(rep.set_index('member_id')['panel_mm_id'])
    chunks.append(chunk)

df2 = pd.concat(chunks, ignore_index=True)
你需要将每个块附加到一个列表中,然后使用concat来将它们全部连接起来,我认为ignore_index可能不是必需的,但我可能错了。

1
我只需要在列表中吗?就这样?我想问题可能是另一个。谢谢!但是之后我遇到了另一个问题:pandas.io.common.CParserError: Error tokenizing data. C error: out of memory。即使使用chunksize也没有帮助。有什么方法可以解决这个问题吗? - Petr Petrov
当然可以!但是之后我遇到了另一个问题:pandas.io.common.CParserError:数据标记化出错。C错误:内存不足。即使使用chunksize也无法解决。有办法解决这个问题吗? - Petr Petrov
这个错误发生在哪里?是在最后的连接部分吗?如果是,您可能需要编写并附加每个块,例如:for chunk in df2: chunk.ID.map(rep.set_index('member_id')['panel_mm_id']).to_csv(output_dir, modex='a') - EdChum
有没有其他的方法可以连接它? - Petr Petrov
@nikhilvj,你提到的内存错误无论是整个读取CSV文件还是分块读取都不会得到解决,所以你的评论是无关的。读取大型CSV文件所需的内存并不会因此而得到解决。此外,OP在他们的问题中从未提到过这个问题,这只是一个后续评论。 - EdChum

10

最后一行必须按照以下格式:

df2=pd.concat([df1,df2,df3,df4,...], ignore_index=True)

事实上,需要连接的数据帧需要作为列表/元组传递。


6

就像他们所说的,你需要将它作为一个列表传递。另外,在使用concat之前,确保它是一个DataFrame可能会有所帮助。

例如:

chunks = pd.DataFrame(chunks)
df2 = pd.concat([chunks], ignore_index=True)

0
finalexcelsheet = pd.DataFrame()

for file in filenames:
    df = pd.read_excel(file, sheet_name='DL PRB')
    finalexcelsheet = finalexcelsheet.append(
        df, ignore_index=True)

# finalexcelsheet dataframe contain all files data.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接