首页 > 解决方案 > 合并多个数据框保留列并用 NaN 填充其余部分

问题描述

我有一组数据框df1, df2, ... dfn

dfs 是这样的:

 id  |    date    | metric_value
001  | 2013-01-01 |     0.73
001  | 2013-03-01 |     0.73
002  | 2013-01-01 |     0.73
002  | 2013-02-01 |     0.73

id但是and列之间不一定匹配date,所以我可以有一个 df1 像:

 id  |    date    | metric_value1
001  | 2013-01-01 |     0.73
001  | 2013-03-01 |     0.73
002  | 2013-01-01 |     0.73
002  | 2013-02-01 |     0.73
004  | 2013-03-01 |     0.73

和一个像df2这样的:

id   |    date    | metric_value2
001  | 2013-01-01 |     0.72
003  | 2013-02-01 |     0.72
003  | 2013-03-01 |     0.72
004  | 2013-01-01 |     0.72

一般来说df1 ... dfn,我如何合并 df1 和 df2,所以我可以有类似的东西:

id   |    date    | metric_value1  | metric_value2
001  | 2013-01-01 |     0.73       |       0.72
001  | 2013-02-01 |      Nan       |       Nan
001  | 2013-03-01 |     0.73       |       Nan
002  | 2013-01-01 |     0.73       |       Nan
002  | 2013-02-01 |     0.73       |       Nan
002  | 2013-03-01 |      Nan       |       Nan
003  | 2013-01-01 |      Nan       |       Nan
003  | 2013-02-01 |      Nan       |       0.72
003  | 2013-03-01 |      Nan       |       0.72
004  | 2013-01-01 |      Nan       |       0.72
004  | 2013-02-01 |      Nan       |       Nan
004  | 2013-03-01 |     0.73       |       Nan

覆盖整个日期范围内的所有 ID,从最小日期到最大日期

标签: pythonpandasdataframejoinmerge

解决方案


将@JonathanLeon 解决方案更进一步:

import io
import pandas as pd

data='''id|date|metric_value1
001|2013-01-01|0.73
001|2013-03-01|0.73
002|2013-01-01|0.73
002|2013-02-01|0.73
004|2013-03-01|0.73'''
df1 = pd.read_csv(io.StringIO(data), sep='|', engine='python')

data='''id|date|metric_value2
001|2013-01-01|0.72
003|2013-02-01|0.72
003|2013-03-01|0.72
004|2013-01-01|0.72'''
df2 = pd.read_csv(io.StringIO(data), sep='|', engine='python')

df_out = df1.merge(df2, on=['id', 'date'], how='outer')

df_out['date'] = pd.to_datetime(df_out['date'])

df_out.set_index(['id', 'date'])\
      .reindex(pd.MultiIndex.from_product([df_out['id'].unique(),
                                           df_out['date'].unique()],
                                          names=['id', 'date']))\
      .sort_index()
      .reset_index()

输出:

    id       date  metric_value1  metric_value2
0    1 2013-01-01           0.73           0.72
1    1 2013-02-01            NaN            NaN
2    1 2013-03-01           0.73            NaN
3    2 2013-01-01           0.73            NaN
4    2 2013-02-01           0.73            NaN
5    2 2013-03-01            NaN            NaN
6    3 2013-01-01            NaN            NaN
7    3 2013-02-01            NaN           0.72
8    3 2013-03-01            NaN           0.72
9    4 2013-01-01            NaN           0.72
10   4 2013-02-01            NaN            NaN
11   4 2013-03-01           0.73            NaN

推荐阅读