【问题标题】:How to merge dataframes and fill values如何合并数据框和填充值
【发布时间】:2021-01-05 14:36:26
【问题描述】:

我正在尝试合并下面的 2 个 DataFrame 以获得一个输出,其中每个代码都在每个日期列出,如果该代码不在该日期的原始数据框中,则数量填充为 0。我在下面放了一个输入和所需输出的示例,但我的实时数据将包含超过一年的日期和超过 20,000 个代码。

输入数据:

df1

    date
0   2021-05-03
1   2021-05-04
2   2021-05-05
3   2021-05-06
4   2021-05-07
5   2021-05-08
6   2021-05-09
7   2021-05-10

df2

    date      code  qty
0   2021-05-03  A   2
1   2021-05-06  A   5
2   2021-05-07  A   4
3   2021-05-08  A   5
4   2021-05-10  A   6
5   2021-05-04  B   1
6   2021-05-08  B   4

期望的输出:

date      code  qty
03/05/2021  A   2
03/05/2021  B   0
04/05/2021  A   0
04/05/2021  B   1
05/05/2021  A   0
05/05/2021  B   0
06/05/2021  A   5
06/05/2021  B   0
07/05/2021  A   4
07/05/2021  B   0
08/05/2021  A   5
08/05/2021  B   4
09/05/2021  A   0
09/05/2021  B   0
10/05/2021  A   6
10/05/2021  B   0

我尝试了以下合并,但我得到的输出似乎并不如预期:

df_new = df1.merge(df2, how='left', on='date')


    date      code  qty
0   2021-05-03  A   2.0
1   2021-05-04  B   1.0
2   2021-05-05  NaN NaN
3   2021-05-06  A   5.0
4   2021-05-07  A   4.0
5   2021-05-08  A   5.0
6   2021-05-08  B   4.0
7   2021-05-09  NaN NaN
8   2021-05-10  A   6.0

【问题讨论】:

  • 我假设您想要日期和代码的所有组合,对吗?
  • 是的,我正在尝试获取日期和代码的所有组合

标签: python pandas dataframe merge


【解决方案1】:

这更适合reindex。您创建所有组合,设置索引,为所有这些组合重新索引,填充然后重置索引。

import pandas as pd

idx = pd.MultiIndex.from_product([df1.date, df2['code'].unique()],
                                 names=['date', 'code'])

df2 = (df2.set_index(['date', 'code'])
          .reindex(idx)
          .fillna(0, downcast='infer')
          .reset_index())

          date code  qty
0   2021-05-03    A    2
1   2021-05-03    B    0
2   2021-05-04    A    0
3   2021-05-04    B    1
4   2021-05-05    A    0
5   2021-05-05    B    0
6   2021-05-06    A    5
7   2021-05-06    B    0
8   2021-05-07    A    4
9   2021-05-07    B    0
10  2021-05-08    A    5
11  2021-05-08    B    4
12  2021-05-09    A    0
13  2021-05-09    B    0
14  2021-05-10    A    6
15  2021-05-10    B    0

【讨论】:

  • 我觉得应该是from_product([df1.date.unique() + df2.date.unique(), df2.code.unique()]
  • @FloLie 对于日期,因为它是 'left' 合并,我假设基础应该只是 df1。代码可以这样完成,但如果只有 2 个,并且 df2 可能缺少它,那么只指定它们可能会更安全。
  • 不错,应该把['A','B']换成df2.code.unique()
  • @ALollz,你是对的,这取决于假设。对于日期,如果 df1 是完整的日历,但对于代码,我会将 ["A","B"] 标记为名为 all_codes 的变量,否则从 df2 获取唯一值
【解决方案2】:

pivotstack 的一个选项:

(df2.pivot_table(index='date', columns='code', fill_value=0)
    .reindex(df1.date, fill_value=0)
    .stack('code')
    .reset_index()
)

输出:

          date code  qty
0   2021-05-03    A    2
1   2021-05-03    B    0
2   2021-05-04    A    0
3   2021-05-04    B    1
4   2021-05-05    A    0
5   2021-05-05    B    0
6   2021-05-06    A    5
7   2021-05-06    B    0
8   2021-05-07    A    4
9   2021-05-07    B    0
10  2021-05-08    A    5
11  2021-05-08    B    4
12  2021-05-09    A    0
13  2021-05-09    B    0
14  2021-05-10    A    6
15  2021-05-10    B    0

【讨论】:

    【解决方案3】:

    df1unique valscode 之间做一个cross-join。然后使用df.fillna():

    In [480]: x = pd.DataFrame(df2.code.unique())
    
    In [483]: y = df1.assign(key=1).merge(x.assign(key=1), on='key').drop('key', 1).rename(columns={0: 'code'})
    
    In [486]: res = y.merge(df2, how='left').fillna(0)
    
    In [487]: res
    Out[487]: 
              date code  qty
    0   2021-05-03    A  2.0
    1   2021-05-03    B  0.0
    2   2021-05-04    A  0.0
    3   2021-05-04    B  1.0
    4   2021-05-05    A  0.0
    5   2021-05-05    B  0.0
    6   2021-05-06    A  5.0
    7   2021-05-06    B  0.0
    8   2021-05-07    A  4.0
    9   2021-05-07    B  0.0
    10  2021-05-08    A  5.0
    11  2021-05-08    B  4.0
    12  2021-05-09    A  0.0
    13  2021-05-09    B  0.0
    14  2021-05-10    A  6.0
    15  2021-05-10    B  0.0
    

    【讨论】:

      猜你喜欢
      • 2020-10-28
      • 2021-11-14
      • 2019-11-30
      • 1970-01-01
      • 1970-01-01
      • 2013-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多