【问题标题】:Merge Multiples Dataframes preserving columns and filling with NaN the rest合并多个数据框保留列并用 NaN 填充其余部分
【发布时间】:2021-08-07 22:15:40
【问题描述】:

我有一组数据框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

iddate 列之间不一定匹配,所以我可以有一个 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 和 df2,一般来说 df1 ... dfn,所以我可以有类似的东西:

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,从最小日期到最大日期

【问题讨论】:

    标签: python pandas dataframe join merge


    【解决方案1】:

    试试:

    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')
    
    df1.merge(df2, on=['id', 'date'], how='outer')
    

    输出:

       id        date  metric_value1  metric_value2
    0   1  2013-01-01          0.730          0.720
    1   1  2013-03-01          0.730            NaN
    2   2  2013-01-01          0.730            NaN
    3   2  2013-02-01          0.730            NaN
    4   4  2013-03-01          0.730            NaN
    5   3  2013-02-01            NaN          0.720
    6   3  2013-03-01            NaN          0.720
    7   4  2013-01-01            NaN          0.720
    

    【讨论】:

      【解决方案2】:

      进一步了解@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
      

      【讨论】:

      • 太棒了!这真的是我想要的。这段代码是否可以推广到 N 个 dfs,每个 dfs 都有不同的 metric_values?我可以这样合并 N 个数据框吗?
      • 合并一次只能处理两个数据帧。您可以使用 join 来连接许多数据框,但您必须首先将“连接”列移动到所有数据框的索引中。
      • 如果我得到 df_out 并与 df3 合并,并且继续使用 N 个数据帧继续这样做,它会起作用吗?这将如何将您的“加入”列首先移动到所有数据帧的索引中?
      • 是的,你可以合并 df_out 和 df3 等等。但是,如果您使用 join,您可以一次完成所有操作。 df1.join([df2,df3,...]) 如果索引正确对齐。
      【解决方案3】:
      import pandas
      import datetime
      
      #build your list of unique ids
      ids = pandas.concat([df1['id'], df2['id']])
      ids = pandas.Series(ids.unique())
      
      #can do as above to get all possible dates, I've just generated them.
      dates = pandas.DataFrame(pandas.date_range(datetime.date.today(), freq='D', periods = 10), columns=['date'])
      
      #use merge to generate the cartesian product of all dates and all ids
      combinations = pandas.merge(left=dates, right=pandas.DataFrame(ids.unique(), columns=['id']), how='outer', left_index=True, right_index=True)
      
      #merge your dataframes on your 'key' columns
      df3 = pandas.merge(left=dates, right=df1, on=['date', 'id'], how='left')
      df4 = pandas.merge(left=dates, right=df2, on=['date', 'id'], how='left')
      

      【讨论】:

        猜你喜欢
        • 2022-12-10
        • 1970-01-01
        • 2020-10-13
        • 1970-01-01
        • 2020-10-26
        • 2017-10-16
        • 2022-01-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多