bugfix> python > 投稿

以下の2つのデータフレームをマージして、各コードが各日付にリストされ、コードがその日付の元のデータフレームになかった場合は数量が0として入力される出力を取得しようとしています。入力と目的の出力の例を以下に示しますが、ライブデータには1年以上の日付と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

回答 3 件
  • これは、 reindex 。すべての組み合わせを作成し、インデックスを設定し、それらすべての組み合わせにインデックスを再作成し、fillnaしてから、インデックスをリセットします。

    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
    
    

  • 1つのオプション pivot そして stack

    (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
    
    

  • 行う cross-join の間に df1 そして unique valscode 。次に、 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
    
    

あなたの答え