【发布时间】:2018-11-25 22:19:40
【问题描述】:
假设我有 4 个小的 DataFrames
df1、df2、df3 和 df4
import pandas as pd
from functools import reduce
import numpy as np
df1 = pd.DataFrame([['a', 1, 10], ['a', 2, 20], ['b', 1, 4], ['c', 1, 2], ['e', 2, 10]])
df2 = pd.DataFrame([['a', 1, 15], ['a', 2, 20], ['c', 1, 2]])
df3 = pd.DataFrame([['d', 1, 10], ['e', 2, 20], ['f', 1, 1]])
df4 = pd.DataFrame([['d', 1, 10], ['e', 2, 20], ['f', 1, 15]])
df1.columns = ['name', 'id', 'price']
df2.columns = ['name', 'id', 'price']
df3.columns = ['name', 'id', 'price']
df4.columns = ['name', 'id', 'price']
df1 = df1.rename(columns={'price':'pricepart1'})
df2 = df2.rename(columns={'price':'pricepart2'})
df3 = df3.rename(columns={'price':'pricepart3'})
df4 = df4.rename(columns={'price':'pricepart4'})
上面创建的是4个DataFrame,我想要的在下面的代码中。
# Merge dataframes
df = pd.merge(df1, df2, left_on=['name', 'id'], right_on=['name', 'id'], how='outer')
df = pd.merge(df , df3, left_on=['name', 'id'], right_on=['name', 'id'], how='outer')
df = pd.merge(df , df4, left_on=['name', 'id'], right_on=['name', 'id'], how='outer')
# Fill na values with 'missing'
df = df.fillna('missing')
所以我已经为没有很多行和列的 4 个 DataFrame 实现了这一点。
基本上,我想将上述外部合并解决方案扩展到大小为 62245 X 3 的 MULTIPLE (48) DataFrames:
所以我从另一个使用 lambda reduce 的 StackOverflow 答案构建,提出了这个解决方案:
from functools import reduce
import pandas as pd
import numpy as np
dfList = []
#To create the 48 DataFrames of size 62245 X 3
for i in range(0, 49):
dfList.append(pd.DataFrame(np.random.randint(0,100,size=(62245, 3)), columns=['name', 'id', 'pricepart' + str(i + 1)]))
#The solution I came up with to extend the solution to more than 3 DataFrames
df_merged = reduce(lambda left, right: pd.merge(left, right, left_on=['name', 'id'], right_on=['name', 'id'], how='outer'), dfList).fillna('missing')
这导致MemoryError。
我不知道该怎么做才能阻止内核死机..我已经坚持了两天..我执行的 EXACT 合并操作的一些代码不会导致 MemoryError 或能给你同样结果的东西,将不胜感激。
此外,主 DataFrame 中的 3 列(不是示例中可重现的 48 个 DataFrame)的类型为 int64、int64 和 float64,我希望它们保持这种状态,因为整数和它所代表的浮动。
编辑:
我没有反复尝试运行合并操作或使用 reduce lambda 函数,而是以 2 个一组来完成它!另外,我更改了一些列的数据类型,有些不需要是float64。所以我把它归结为float16。它走得很远,但最终还是抛出了MemoryError。
intermediatedfList = dfList
tempdfList = []
#Until I merge all the 48 frames two at a time, till it becomes size 2
while(len(intermediatedfList) != 2):
#If there are even number of DataFrames
if len(intermediatedfList)%2 == 0:
#Go in steps of two
for i in range(0, len(intermediatedfList), 2):
#Merge DataFrame in index i, i + 1
df1 = pd.merge(intermediatedfList[i], intermediatedfList[i + 1], left_on=['name', 'id'], right_on=['name', 'id'], how='outer')
print(df1.info(memory_usage='deep'))
#Append it to this list
tempdfList.append(df1)
#After DataFrames in intermediatedfList merging it two at a time using an auxillary list tempdfList,
#Set intermediatedfList to be equal to tempdfList, so it can continue the while loop.
intermediatedfList = tempdfList
else:
#If there are odd number of DataFrames, keep the first DataFrame out
tempdfList = [intermediatedfList[0]]
#Go in steps of two starting from 1 instead of 0
for i in range(1, len(intermediatedfList), 2):
#Merge DataFrame in index i, i + 1
df1 = pd.merge(intermediatedfList[i], intermediatedfList[i + 1], left_on=['name', 'id'], right_on=['name', 'id'], how='outer')
print(df1.info(memory_usage='deep'))
tempdfList.append(df1)
#After DataFrames in intermediatedfList merging it two at a time using an auxillary list tempdfList,
#Set intermediatedfList to be equal to tempdfList, so it can continue the while loop.
intermediatedfList = tempdfList
有什么办法可以优化我的代码以避免MemoryError,我什至使用了 AWS 192GB RAM(我现在欠他们 7 美元,我本可以给你一个),这比我更远'已经得到了,在将 28 个 DataFrame 的列表减少到 4 个之后,它仍然抛出 MemoryError ..
【问题讨论】:
-
@coldspeed 如果我没记错的话,你的答案中的 concat 应该正确地进行外部合并,正如你的答案的输出所显示的那样 - 在 Abhishek 的示例中,你得到的答案与他确实做到了,而不是您使用“内部”获得的空 DataFrame。
-
@MarcoSpinaci 是这样吗? ...嗯,有趣,感谢您的澄清!
标签: python pandas dataframe merge out-of-memory