混合/合并两个半完整的熊猫数据框

时间:2019-11-01 19:15:31

标签: python pandas dataframe

我有两个具有相似但不完整数据的Pandas DataFrame。它主要是与国家/地区有关的数据,因此下面是一些伪造Population (millions)数据的示例:

表A

| Country | 2014 | 2015 | 2016 | 2017 | 2018 |
|--------:|------|------|------|------|------|
| USA     | nan  | nan  | 323  | 325  | 328  |
| UK      | nan  | nan  | nan  | 63   | 65   |
| India   | nan  | nan  | 800  | nan  | 1100 |
| China   | nan  | nan  | 1100 | 1200 | 1300 |

表B

| Country | 2014 | 2015 | 2016 | 2017 | 2019 |
|--------:|------|------|------|------|------|
| USA     | 319  | 321  | 324  | nan  | 330  |
| UK      | 58   | 60   | nan  | nan  | 68   |
| India   | 780  | 810  | 820  | nan  | 1300 |
| Nigeria | 90   | 100  | 105  | nan  | 110  |

从上面,我试图证明我发现的数据集的一些特征:

  • 有时两个df都有一个值条目(例如,India 2016),会有所不同
  • 有时两个df都缺少某些条目(例如:UK 2016)
  • 有时一个表中存在行,而另一表中不存在(例如:尼日利亚,中国)
  • 有时一个表中存在一列,但另一个表中不存在(例如:表A中的2018年,表B中的2019年)

因此,我想将它们组合起来,使得nan在表B中填充(如果存在),并且在列和行不存在的情况下添加它们。如果有冲突,我不在乎使用哪一个(差异不够明显)。

基本上,我希望结果看起来像这样(在这种情况下,出现平局时将使用表B值):

表A联合表B

| Country | 2014 | 2015 | 2016 | 2017 | 2018 | 2019 |
|--------:|------|------|------|------|------|------|
| USA     | 319  | 321  | 323  | 325  | 328  | 330  |
| UK      | 58   | 60   | nan  | 63   | 65   | 68   |
| India   | 780  | 810  | 820  | nan  | 1100 | 1300 |
| China   | nan  | nan  | 1100 | 1200 | 1300 | nan  |
| Nigeria | 90   | 100  | 105  | nan  | nan  | 110  |

直觉上,我只是希望表格尽可能完整。有没有一种方法,而不必运行for循环?桌子很大,我不想写一个长循环。

3 个答案:

答案 0 :(得分:2)

使用:

df_join=( df2.merge(df1,how='outer')
           .groupby('Country')
           .apply(lambda x: x.ffill().bfill())
           .drop_duplicates('Country') )
print(df_join)

   Country   2014   2015    2016    2017    2019    2018
0      USA  319.0  321.0   324.0   325.0   330.0   328.0
1       UK   58.0   60.0     NaN    63.0    68.0    65.0
2    India  780.0  810.0   820.0     NaN  1300.0  1100.0
3  Nigeria   90.0  100.0   105.0     NaN   110.0     NaN
7    China    NaN    NaN  1100.0  1200.0     NaN  1300.0

答案 1 :(得分:1)

您可以使用concatgroupby

(pd.concat([df1,df2], sort=False)
   .groupby('Country', sort=False,as_index=False)
   .agg('first')
)

输出:

   Country   2014   2015    2016    2017    2018    2019
0      USA  319.0  321.0   323.0   325.0   328.0   330.0
1       UK   58.0   60.0     NaN    63.0    65.0    68.0
2    India  780.0  810.0   800.0     NaN  1100.0  1300.0
3    China    NaN    NaN  1100.0  1200.0  1300.0     NaN
4  Nigeria   90.0  100.0   105.0     NaN     NaN   110.0

答案 2 :(得分:0)

您可以这样做:

f :: (b -> c -> d) -> (b, c) -> d

输出

result = pd.concat([A.melt(id_vars='Country', var_name='Year', value_name='Population'),
                    B.melt(id_vars='Country', var_name='Year', value_name='Population')]).dropna()

print(pd.crosstab(index=result.Country, columns=result.Year, values=result.Population, aggfunc='mean'))