【问题标题】:pandas Datafram: Add every month of a whole year starting from Dec to Dec for every new Personpandas Dataframe:从 Dec 到 Dec 为每个新人添加一整年的每个月
【发布时间】:2023-02-01 14:35:08
【问题描述】:

我有一个这样的数据框。

M_Yr       Type    ID      Name   Sum  
12/31/22   CASH    3512           23
12/31/22   CASH    3513    Mike   3
12/31/22   CASH    3514    Mo     4
12/31/22   CASH    3515    Mary   5
12/31/22   CASH    3516    Mel    10
12/31/22   CASH    3517    Mop    2
12/31/22   CASH    3518    Me     7
1/31/23    CASH    3512           0
1/31/23    CASH    3514    Mo     0
1/31/23    CASH    3515    Mary   -2
1/31/23    CASH    3516    Mel    0
1/31/23    CASH    3517    Mop    2
3/30/23    CASH    3512           6
3/30/23    CASH    3518    Me     0
3/30/23    CASH    3514    Mo     3
3/30/23    CASH    3515    Mary   0
3/30/23    CASH    3516    Mel    0
3/30/23    CASH    3517    Mop    2 
5/31/23    CASH    3512           -2
5/31/23    CASH    3518    Me     3
5/31/23    CASH    3514    Mo     0
5/31/23    CASH    3515    Mary   0
5/31/23    CASH    3516    Mel    1
5/31/23    CASH    3517    Mop    0 
7/31/23    CASH    3512           0
7/31/23    CASH    3518    Me     3
7/31/23    CASH    3514    Mo     0
7/31/23    CASH    3515    Mary   1
7/31/23    CASH    3516    Mel    0
7/31/23    CASH    3517    Mop    0 
8/31/23    CASH    3512           2
8/31/23    CASH    3518    Me     -3
8/31/23    CASH    3514    Mo     0
11/30/23   CASH    3512           0
12/31/23   CASH    3518    Me     3

我想让 Dataframe 为每个 Name 打印一整年的每个 M_Yr,并使用给出的第一个数字作为起点找到每个月的 sum col 的新总和,一旦你得到,前几个月就不会改变该月的新总和,因此生成的 Dataframe 应如下所示:

M_Yr       Type    ID      Name   Sum  
12/31/22   CASH    3512           23
12/31/22   CASH    3513    Mike   3
12/31/22   CASH    3514    Mo     4
12/31/22   CASH    3515    Mary   5
12/31/22   CASH    3516    Mel    10
12/31/22   CASH    3517    Mop    2
12/31/22   CASH    3518    Me     7
1/31/23    CASH    3512           23
1/31/23    CASH    3513    Mike   3
1/31/23    CASH    3514    Mo     4
1/31/23    CASH    3515    Mary   3
1/31/23    CASH    3516    Mel    10
1/31/23    CASH    3517    Mop    4
1/31/23    CASH    3518    Me     7
2/30/23    CASH    3512           23
2/30/23    CASH    3513    Mike   3
2/30/23    CASH    3514    Mo     4
2/30/23    CASH    3515    Mary   3
2/30/23    CASH    3516    Mel    10
2/30/23    CASH    3517    Mop    4
2/30/23    CASH    3518    Me     7
3/31/23    CASH    3512           29
3/31/23    CASH    3513    Mike   3
3/31/23    CASH    3514    Mo     7
3/31/23    CASH    3515    Mary   3
3/31/23    CASH    3516    Mel    10
3/31/23    CASH    3517    Mop    6
3/31/23    CASH    3518    Me     7
4/30/23    CASH    3512           23
4/30/23    CASH    3513    Mike   3
4/30/23    CASH    3514    Mo     7
4/30/23    CASH    3515    Mary   3
4/30/23    CASH    3516    Mel    10
4/30/23    CASH    3517    Mop    6
4/30/23    CASH    3518    Me     7
5/31/23    CASH    3512           27
5/31/23    CASH    3513    Mike   3
5/31/23    CASH    3514    Mo     7
5/31/23    CASH    3515    Mary   3
5/31/23    CASH    3516    Mel    11
5/31/23    CASH    3517    Mop    6
5/31/23    CASH    3518    Me     10
6/30/23    CASH    3512           23
6/30/23    CASH    3513    Mike   3
6/30/23    CASH    3514    Mo     7
6/30/23    CASH    3515    Mary   3
6/30/23    CASH    3516    Mel    11
6/30/23    CASH    3517    Mop    6
6/30/23    CASH    3518    Me     10
7/31/23    CASH    3512           23
7/31/23    CASH    3513    Mike   3
7/31/23    CASH    3514    Mo     7
7/31/23    CASH    3515    Mary   4
7/31/23    CASH    3516    Mel    11
7/31/23    CASH    3517    Mop    6
7/31/23    CASH    3518    Me     13
8/30/23    CASH    3512           29
8/30/23    CASH    3513    Mike   3
8/30/23    CASH    3514    Mo     7
8/30/23    CASH    3515    Mary   4
8/30/23    CASH    3516    Mel    11
8/30/23    CASH    3517    Mop    6
8/30/23    CASH    3518    Me     10
9/31/23    CASH    3512           29
9/31/23    CASH    3513    Mike   3
9/31/23    CASH    3514    Mo     7
9/31/23    CASH    3515    Mary   4
9/31/23    CASH    3516    Mel    11
9/31/23    CASH    3517    Mop    6
9/31/23    CASH    3518    Me     10
10/31/23   CASH    3512           29
10/31/23   CASH    3513    Mike   3
10/31/23   CASH    3514    Mo     7
10/31/23   CASH    3515    Mary   4
10/31/23   CASH    3516    Mel    11
10/31/23   CASH    3517    Mop    6
10/31/23   CASH    3518    Me     10
11/30/23   CASH    3512           29
11/30/23   CASH    3513    Mike   3
11/30/23   CASH    3514    Mo     7
11/30/23   CASH    3515    Mary   4
11/30/23   CASH    3516    Mel    11
11/30/23   CASH    3517    Mop    6
11/30/23   CASH    3518    Me     10
12/31/23   CASH    3512           29
12/31/23   CASH    3513    Mike   3
12/31/23   CASH    3514    Mo     7
12/31/23   CASH    3515    Mary   4
12/31/23   CASH    3516    Mel    11
12/31/23   CASH    3517    Mop    6
12/31/23   CASH    3518    Me     13

不确定如何接近

【问题讨论】:

  • 你试过什么?这不是代码编写服务。请注意,在将数据输入 pandas 之前,使用您的数据可能更容易完成此类操作。

标签: python pandas dataframe


【解决方案1】:

首先将DataFrame.reindexMultiIndex.from_product 的所有列组合一起使用,然后通过GroupBy.cumsum 使用每组的累计和:

df = (df.set_index(["M_Yr","Type","ID", "Name"])
        .reindex(pd.MultiIndex.from_product([df["M_Yr"].unique(),
                                             df["Type"].unique(),
                                             df["ID"].unique(),
                                             df["Name"].unique()], 
                                             names=["M_Yr","Type","ID", "Name"]), 
                  fill_value=0)
        .reset_index())

df['Sum'] = df.groupby(['Type','ID','Name'], dropna=False)['Sum'].cumsum()
print (df.tail(10))
        M_Yr  Type    ID  Name  Sum
46  11/30/23  CASH  3512   Mel   11
47  11/30/23  CASH  3512   Mop    6
48  11/30/23  CASH  3512    Me   10
49  12/31/23  CASH  3512   NaN   29
50  12/31/23  CASH  3512  Mike    3
51  12/31/23  CASH  3512    Mo    7
52  12/31/23  CASH  3512  Mary    4
53  12/31/23  CASH  3512   Mel   11
54  12/31/23  CASH  3512   Mop    6
55  12/31/23  CASH  3512    Me   13

编辑:答案由Series.map通过ids的原始名称编辑映射:

d = df.set_index('ID')['Name'].to_dict()    

df = (df.set_index(["M_Yr","Type","ID"])
        .reindex(pd.MultiIndex.from_product([df["M_Yr"].unique(),
                                             df["Type"].unique(),
                                             df["ID"].unique()], 
                                             names=["M_Yr","Type", "ID"]), 
                  fill_value=0)
        .reset_index())

df['Sum'] = df.groupby(['Type','ID'], dropna=False)['Sum'].cumsum()

df['Name'] = df['ID'].map(d)
print (df.tail(10))
        M_Yr  Type    ID  Name  Sum
46  11/30/23  CASH  3516   Mel   11
47  11/30/23  CASH  3517   Mop    6
48  11/30/23  CASH  3518    Me   10
49  12/31/23  CASH  3512   NaN   29
50  12/31/23  CASH  3513  Mike    3
51  12/31/23  CASH  3514    Mo    7
52  12/31/23  CASH  3515  Mary    4

EDIT1:首先为避免重复是所有 4 列的聚合 sum

df = df.groupby(["M_Yr","Type","ID", "Name"], as_index=False, dropna=False)['Sum'].sum()

d = df.set_index('ID')['Name'].to_dict()  

然后添加缺少的月份使用月份:

df["M_Yr"] = pd.to_datetime(df["M_Yr"]).dt.to_period('m')

dates = pd.period_range(df["M_Yr"].min(), df['M_Yr'].max(), freq='m')

所以reindex添加所有缺失的组合:

df = (df.set_index(["M_Yr","Type","ID"])
        .reindex(pd.MultiIndex.from_product([dates,
                                             df["Type"].unique(),
                                             df["ID"].unique()], 
                                             names=["M_Yr","Type", "ID"]), 
                  fill_value=0)
        .reset_index())

然后每组累计总和,映射Name并将月份转换为格式为MM/DD/YYYY的日期:

df['Sum'] = df.groupby(['Type','ID'], dropna=False)['Sum'].cumsum()

df['Name'] = df['ID'].map(d)

df['M_Yr'] = df['M_Yr'].dt.to_timestamp(how='e').dt.strftime('%m/%d/%Y')
print (df)
          M_Yr  Type    ID  Name   Sum
0   12/31/2022  CASH  3512     2   0.0
1   12/31/2022  CASH  3514    Mo   4.0
2   12/31/2022  CASH  3515  Mary   5.0
3   12/31/2022  CASH  3516   Mel  10.0
4   12/31/2022  CASH  3517   Mop   2.0
..         ...   ...   ...   ...   ...
86  12/31/2023  CASH  3515  Mary   4.0
87  12/31/2023  CASH  3516   Mel  11.0
88  12/31/2023  CASH  3517   Mop   6.0
89  12/31/2023  CASH  3513  Mike   3.0
90  12/31/2023  CASH  3518    Me  13.0

[91 rows x 5 columns]

【讨论】:

  • 我忘了补充一点,每个名字都有一个唯一的 ID,并不是所有的名字都是 3512,这使得代码不起作用
  • @DumbCoder - 你能用这个改变数据吗?因为很难知道如何改变我的解决方案。
  • 我进行了更改,希望它现在更有意义
  • 我收到 ValueError:无法处理非唯一多索引!
  • @DumbCoder - 在解决方案聚合之前 sum 就像 df = df.groupby(["M_Yr","Type","ID", "Name"], as_index=False, dropna=False)['Sum'].sum()
猜你喜欢
  • 2021-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 2018-11-28
  • 1970-01-01
  • 2021-05-05
相关资源
最近更新 更多