python - pandas 中的高效链合并

标签 python pandas merge

我发现当您将大量数据集与同一列的大量列合并时,直接与 pandas 库进行链式合并的效率非常低。

问题的根源和我们加入很多str的笨办法是一样的:

joined = reduce(lambda a + b, str_list)

代替:

joined = ''.join(str_list)

进行链式合并时,我们多次复制数据集(在我的例子中几乎复制了 100 次),而不是一次或按顺序填充多个数据集中的列。

是否有一些有效的方法(= 线性复杂度由集合的数量决定)通过同一列链接合并大量数据集?

最佳答案

如果您有数据帧列表 dfs:

dfs = [df1, df2, df3, ... , dfn]

您可以使用 Pandas 的 concat 加入他们据我所知,该功能比链接合并更快。 concat 仅根据索引(而非列)连接数据帧,但通过一些预处理,您可以模拟 merge 操作。

首先将 dfs 中每个数据帧的索引替换为您要合并的列。假设您要在 "A" 列上合并:

dfs = [df.set_index("A", drop=True) for df in dfs]

请注意,这覆盖以前的索引(无论如何合并都会这样做)所以您可能希望将这些索引保存在某个地方(如果您以后出于某种原因需要它们)。

现在我们可以使用 concat,它基本上会在索引上合并(这实际上是您的列!!)

merged = pd.concat(dfs, axis=1, keys=range(len(dfs)), join='outer', copy=False)

join= 参数可以是'inner''outer'(默认)。 copy= 参数使 concat 不会对数据帧进行不必要的复制。

然后您可以将 "A" 保留为索引,或者您可以通过执行以下操作将其返回到列中:

merged.reset_index(drop=False, inplace=True)

keys= 参数是可选的,它为每个数据帧分配一个键值(在本例中,我给了它一个整数范围,但如果你愿意,你可以给它们其他标签)。这允许您访问原始数据框中的列。所以如果你想获取对应于 dfs 中第 20 个数据帧的列,你可以调用:

merged[20]

如果没有 keys= 参数,它可能会混淆哪些行来自哪些数据帧,尤其是当它们具有相同的列名时。

我仍然不完全确定 concat 是否以线性时间运行,但它肯定比链接 merge 更快:

在随机生成的数据帧列表(10、100 和 1000 个数据帧的列表)上使用 ipython 的 %timeit:

def merge_with_concat(dfs, col):                                             
    dfs = [df.set_index(col, drop=True) for df in dfs]
    merged = pd.concat(dfs, axis=1, keys=range(len(dfs)), join='outer', copy=False)
    return merged

dfs10 = [pd.util.testing.makeDataFrame() for i in range(10)] 
dfs100 = [pd.util.testing.makeDataFrame() for i in range(100)] 
dfs1000 = [pd.util.testing.makeDataFrame() for i in range(1000)] 

%timeit reduce(lambda df1, df2: df1.merge(df2, on="A", how='outer'), dfs10)
10 loops, best of 3: 45.8 ms per loop
%timeit merge_with_concat(dfs10,"A")
100 loops, best of 3: 11.7 ms per loop

%timeit merge_with_concat(dfs100,"A")
10 loops, best of 3: 139 ms per loop
%timeit reduce(lambda df1, df2: df1.merge(df2, on="A", how='outer'), dfs100)
1 loop, best of 3: 1.55 s per loop

%timeit merge_with_concat(dfs1000,"A")
1 loop, best of 3: 9.67 s per loop
%timeit reduce(lambda df1, df2: df1.merge(df2, on="A", how='outer'), dfs1000)
# I killed it after about 5 minutes so the other one is definitely faster

关于python - pandas 中的高效链合并,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40566541/

相关文章:

python - 列出所有连续的子数组

python - 带有偏移量索引的 Pandas 单个时间戳

merge - "TF14083: The item {0} has a pending merge from the current merge operation"合并TFS2008时

svn - Subversion中如何区分普通commit和merge?

python - 散列不确定的对象

python - 使用 Scipy 的 stats.kstest 模块进行拟合优度测试

python - 使用 Python Sympy 和 Latex 计算 10 的幂

arrays - 使用掩码数组创建 pandas DataFrame

python-3.x - 类型错误 : Object of type 'DataFrame' is not JSON serializable

SVN 提交而不更新