具有巨大数据框的内部连接(约 200 万列)
Posted
技术标签:
【中文标题】具有巨大数据框的内部连接(约 200 万列)【英文标题】:inner join with huge dataframes (~2 million columns) 【发布时间】:2019-03-14 16:03:31 【问题描述】:我正在尝试根据在每个数据框中找到的一列(称为“名称”)中的匹配值来连接两个数据框(df1
和 df2
)。我已经尝试过使用 R 的 inner_join
函数以及 Python 的 pandas merge
函数,并且已经能够使两者都在我的数据的较小子集上成功工作。我认为我的问题在于我的数据框的大小。
我的数据框如下:
df1
的“名称”列有 5 个附加列,并且有大约 900 行。
df2
的“名称”列有约 200 万列和约 900 行。
我已经尝试过(在 R 中):
df3 <- inner_join(x = df1, y = df2, by = 'Name')
我也尝试过(在 Python 中,df1
和 df2
是 Pandas 数据框):
df3 = df1.merge(right = df2, how = 'inner', left_on = 1, right_on = 0)
(其中“名称”列位于 df1 的索引 1 和 df2 的索引 0)
当我将上述内容应用于我的完整数据帧时,它会运行很长时间并最终崩溃。此外,我怀疑问题可能出在我的df2
的 200 万列上,所以我尝试将它(按行)子设置为更小的数据帧。我的计划是将df2
的小子集与df1
结合起来,然后在最后将新的数据帧绑定在一起。然而,即使是更小的分区df2
s 也不能成功。
如果有人能提供任何建议,我将不胜感激。
【问题讨论】:
您能谈谈各个对象的内存占用量(以 MB/GB 为单位)以及您可用的操作系统/内存量吗? 尝试使用data.table
。
你的列应该是行吗?重塑为长格式可能会简化事情。
如果内存问题是一个问题,并且您想使用 python,您可以尝试使用 dask 数据框。 docs.dask.org/en/latest/dataframe.html -
这是 1:1、1:many many:1 还是 many:many 合并?
【参考方案1】:
感谢大家的帮助!按照@shadowtalker 的建议使用 data.table,极大地加快了进程。仅供参考,以防万一有人尝试做类似的事情,df1 大约为 400 mb,而我的 df2 文件大约为 3gb。
我能够完成以下任务:
library(data.table)
df1 <- setDT(df1)
df2 <- setDT(df2)
setkey(df1, Name)
setkey(df2, Name)
df3 <- df1[df2, nomatch = 0]
【讨论】:
【参考方案2】:这是一个非常丑陋的解决方法,我分解了 df2 的列并逐个添加它们。不确定它是否会起作用,但可能值得一试:
# First, I only grab the "Name" column from df2
df3 = df1.merge(right=df2[["Name"]], how="inner", on="Name")
# Then I save all the column headers (excluding
# the "Name" column) in a separate list
df2_columns = df2.columns[np.logical_not(df2.columns.isin(["Name"]))]
# This determines how many columns are going to get added each time.
num_cols_per_loop = 1000
# And this just calculates how many times you'll need to go through the loop
# given the number of columns you set to get added each loop
num_loops = int(len(df2_columns)/num_cols_per_loop) + 1
for i in range(num_loops):
# For each run of the loop, we determine which rows will get added
this_column_sublist = df2_columns[i*num_cols_per_loop : (i+1)*num_cols_per_loop]
# You also need to add the "Name" column to make sure
# you get the observations in the right order
this_column_sublist = np.append("Name",this_column_sublist)
# Finally, merge with just the subset of df2
df3 = df3.merge(right=df2[this_column_sublist], how="inner", on="Name")
就像我说的,这是一个丑陋的解决方法,但它可能会奏效。
【讨论】:
以上是关于具有巨大数据框的内部连接(约 200 万列)的主要内容,如果未能解决你的问题,请参考以下文章