合并多个DataFrames熊猫

时间:2019-04-12 13:26:04

标签: python pandas dataframe

这可能被认为是a thorough explanation of various approaches的副本,但是由于数据帧数量增加,我似乎无法找到解决问题的方法。

我有多个数据帧(超过10个),每个数据帧在一列VARX中有所不同。这只是一个快速且过于简化的示例:

import pandas as pd

df1 = pd.DataFrame({'depth': [0.500000, 0.600000, 1.300000],
       'VAR1': [38.196202, 38.198002, 38.200001],
       'profile': ['profile_1', 'profile_1','profile_1']})

df2 = pd.DataFrame({'depth': [0.600000, 1.100000, 1.200000],
       'VAR2': [0.20440, 0.20442, 0.20446],
       'profile': ['profile_1', 'profile_1','profile_1']})

df3 = pd.DataFrame({'depth': [1.200000, 1.300000, 1.400000],
       'VAR3': [15.1880, 15.1820, 15.1820],
       'profile': ['profile_1', 'profile_1','profile_1']})

对于每个配置文件,每个df的深度相同或不同,所以

我需要创建一个新的DataFrame,它将合并所有单独的DataFrame,其中用于操作的关键列depthprofile,并带有 all < / strong>为每个配置文件显示深度值。

因此,VARX的值应为NaN,在该位置没有该轮廓的变量的深度测量。

结果应该是一个新的,压缩的DataFrame,其中所有VARX作为depthprofile的附加列,如下所示:

name_profile    depth   VAR1        VAR2        VAR3
profile_1   0.500000    38.196202   NaN         NaN
profile_1   0.600000    38.198002   0.20440     NaN
profile_1   1.100000    NaN         0.20442     NaN
profile_1   1.200000    NaN         0.20446     15.1880
profile_1   1.300000    38.200001   NaN         15.1820
profile_1   1.400000    NaN         NaN         15.1820

请注意,实际的配置文件数量要大得多。

有什么想法吗?

5 个答案:

答案 0 :(得分:7)

考虑在每个数据帧上设置索引,然后使用pd.concat运行水平合并:

dfs = [df.set_index(['profile', 'depth']) for df in [df1, df2, df3]]

print(pd.concat(dfs, axis=1).reset_index())
#      profile  depth       VAR1     VAR2    VAR3
# 0  profile_1    0.5  38.198002      NaN     NaN
# 1  profile_1    0.6  38.198002  0.20440     NaN
# 2  profile_1    1.1        NaN  0.20442     NaN
# 3  profile_1    1.2        NaN  0.20446  15.188
# 4  profile_1    1.3  38.200001      NaN  15.182
# 5  profile_1    1.4        NaN      NaN  15.182

答案 1 :(得分:4)

或使用merge

from functools import partial, reduce

dfs = [df1,df2,df3]
merge = partial(pd.merge, on=['depth','profile'], how='outer')
reduce(merge, dfs)

    depth       VAR1    profile     VAR2    VAR3
0    0.6  38.198002  profile_1  0.20440     NaN
1    0.6  38.198002  profile_1  0.20440     NaN
2    1.3  38.200001  profile_1      NaN  15.182
3    1.1        NaN  profile_1  0.20442     NaN
4    1.2        NaN  profile_1  0.20446  15.188
5    1.4        NaN  profile_1      NaN  15.182

更新

要按照注释中的建议将数据框合并成一个循环,可以执行以下操作:

df_final = pd.DataFrame(columns=df1.columns)
for df in dfs:
    df_final = df_final.merge(df, on=['depth','profile'], how='outer')

答案 2 :(得分:1)

我会使用append。

>>> df1.append(df2).append(df3).sort_values('depth')

        VAR1     VAR2    VAR3  depth    profile
0  38.196202      NaN     NaN    0.5  profile_1
1  38.198002      NaN     NaN    0.6  profile_1
0        NaN  0.20440     NaN    0.6  profile_1
1        NaN  0.20442     NaN    1.1  profile_1
2        NaN  0.20446     NaN    1.2  profile_1
0        NaN      NaN  15.188    1.2  profile_1
2  38.200001      NaN     NaN    1.3  profile_1
1        NaN      NaN  15.182    1.3  profile_1
2        NaN      NaN  15.182    1.4  profile_1

很明显,如果您有很多数据框,只需列出并遍历它们即可。

答案 3 :(得分:1)

为什么不连接所有数据框,合并,然后使用您的ID重新构造它们?可能有一种更有效的方法来执行此操作,但这是可行的。

df=pd.melt(pd.concat([df1,df2,df3]),id_vars=['profile','depth'])
df_pivot=df.pivot_table(index=['profile','depth'],columns='variable',values='value')

df_pivot所在的位置

variable              VAR1     VAR2    VAR3
profile   depth                            
profile_1 0.5    38.196202      NaN     NaN
          0.6    38.198002  0.20440     NaN
          1.1          NaN  0.20442     NaN
          1.2          NaN  0.20446  15.188
          1.3    38.200001      NaN  15.182
          1.4          NaN      NaN  15.182

答案 4 :(得分:1)

您还可以使用:

dfs = [df1, df2, df3]
df = pd.merge(dfs[0], dfs[1], left_on=['depth','profile'], right_on=['depth','profile'], how='outer')
for d in dfs[2:]:
    df = pd.merge(df, d, left_on=['depth','profile'], right_on=['depth','profile'], how='outer')

   depth       VAR1    profile     VAR2    VAR3
0    0.5  38.196202  profile_1      NaN     NaN
1    0.6  38.198002  profile_1  0.20440     NaN
2    1.3  38.200001  profile_1      NaN  15.182
3    1.1        NaN  profile_1  0.20442     NaN
4    1.2        NaN  profile_1  0.20446  15.188
5    1.4        NaN  profile_1      NaN  15.182