【问题标题】:Pandas data frame calculate avegrage of same months last 3 years and append in the same data framePandas 数据框计算过去 3 年同月的平均值并附加在同一数据框中
【发布时间】:2020-03-05 09:14:53
【问题描述】:

我有一个这样的熊猫数据框:

Account Id  Gross Sum   Invoice Type Name      Net Sum Company     Security         Supplier Date Completed YearMonth   Category
710830      282.81      Invoice                282.81              asd5a            Abc      1/1/2018       2018-1      Postal
445800      4868.71     Invoice                3926.4              adc6ac           Def      1/1/2018       2018-1      R&D
710350      282.81      Invoice                282.81              fgn6             Ghi      2/9/2018       2018-2      Other
710510      282.81      Invoice                282.81              dg               jkl      2/9/2018       2018-2      Electricity
710630      841.59      Invoice                707.07              dfvbfbf          mno      3/2/2018       2018-3      Repairs
710610      841.59      Invoice                707.07              rrcv             pqr      3/2/2018       2018-3      Leasing
710810      12.14       Invoice                10.12               btbfd            stu      1/1/2019       2019-1      Telephone
704300      81517.6     Invoice                65740               dfbtt            vwx      1/1/2019       2019-1      Statutory
710510      2105.64     Invoice                1776.53             dfdftb5          dfb      2/9/2019       2019-2      Electricity
710510      2105.64     Invoice                1776.53             ebdfb5b          bcd      2/9/2019       2019-2      Electricity
710920      66.96       Invoice                54                  dfrrt65          efg      3/2/2019       2019-3      Data
700330      239.47      Invoice                239.47              aae3a11          hij      3/2/2019       2019-3      Coffee

我想要的是在计算过去 3 年同月平均值的数据框底部添加行。

例如: 对于 year month 2020-1 计算应该是 for 2020-1 = sum(Net Sum Company) In 2019-1 + sum(Net Sum Company) in 2018-1 + sum(Net Sum Company) In 2017-1 divided by the number of months considered 即 3 ,所以只需要考虑过去三年。这样,我将获得平均值并在底部附加与新行相同的内容,该行只有年月和净总和公司列的平均值。 最终目标是得到这样的数据框:

    Account Id  Gross Sum   Invoice Type Name      Net Sum Company     Security         Supplier Date Completed YearMonth   Category
710830      282.81      Invoice                282.81              asd5a            Abc      1/1/2018       2018-1      Postal
445800      4868.71     Invoice                3926.4              adc6ac           Def      1/1/2018       2018-1      R&D
710350      282.81      Invoice                282.81              fgn6             Ghi      2/9/2018       2018-2      Other
710510      282.81      Invoice                282.81              dg               jkl      2/9/2018       2018-2      Electricity
710630      841.59      Invoice                707.07              dfvbfbf          mno      3/2/2018       2018-3      Repairs
710610      841.59      Invoice                707.07              rrcv             pqr      3/2/2018       2018-3      Leasing
710810      12.14       Invoice                10.12               btbfd            stu      1/1/2019       2019-1      Telephone
704300      81517.6     Invoice                65740               dfbtt            vwx      1/1/2019       2019-1      Statutory
710510      2105.64     Invoice                1776.53             dfdftb5          dfb      2/9/2019       2019-2      Electricity
710510      2105.64     Invoice                1776.53             ebdfb5b          bcd      2/9/2019       2019-2      Electricity
710920      66.96       Invoice                54                  dfrrt65          efg      3/2/2019       2019-3      Data
700330      239.47      Invoice                239.47              aae3a11          hij      3/2/2019       2019-3      Coffee
-              -           -                   34979.66            -                -        -              2020-1      -
-              -           -                   2059.34             -                -        -              2020-2      -
-              -           -                   853.805             -                -        -              2020-3      -

我是 pandas 的新手,因此不胜感激。这必须严格使用 pandas 来完成。

【问题讨论】:

  • 您需要过去 3 年的滚动平均值,对吗?所以它应该是一个单独的列,每个记录都有一个值。在你提出它的方式中,你将实际的净总和与同一列中的一些平均数混合在一起,这似乎不正确。
  • 是的,这种要求。我想将前几年的平均值加到未来几个月的同一列中。你可以说我想以这种方式预测它,最终在 BI 平台上显示在相同的数字过去+未来折线图上。有意义吗?
  • 这里是 2020 年,还是数据框中每月的下一年?
  • @SergeBallesta 这是数据框中的下一年

标签: python pandas


【解决方案1】:

IIUC,你想要:

  • 在数据框中每月查找下一年
  • 过去 3 年每月对 Net Sum Company 列的总和
  • 将每个总和除以月数(样本中为 2 个)以获得月平均值
  • 将这些平均值添加到 YearMonth 列中带有新年和月份的数据框中

代码可以是:

# extract Year and Month Series from the dataframe
year = df['YearMonth'].str.slice(stop=4).astype(int)
month = df['YearMonth'].str.slice(start=5)

# compute the new year per month as max(year) + 1
newyear_month = year.groupby(month).max() + 1

# build a Series aligned with the dataframe from that new year
newyear = pd.DataFrame(month).merge(
    pd.DataFrame(newyear_month),
    left_on='YearMonth', right_index=True, suffixes=('_x', '')
    )['YearMonth'].sort_index()

# compute the sum of relevant years per month
tmp = df.loc[(newyear-3 <= year) & (year <= newyear-1), 'Net Sum Company'
             ].groupby(month).sum()

# divide by the number of distinct month per sum
tmp /= df.groupby(month)['YearMonth'].nunique()

# compute a YearMonth column for that new dataframe
tmp = pd.concat([newyear_month.astype(str), tmp], axis=1)
tmp['YearMonth'] = tmp['YearMonth'] + '-' + tmp.index  # tmp is indexed by month

# force the type of Account Id to object to allow it to contain null values
df['Account Id'] = df['Account Id'].astype(object)

# concat the new rows to the dataframe and reset the index
new_df = df.append(tmp, sort=False).reset_index(drop=True)

对于您的示例,new_df 给出:

   Account Id  Gross Sum Invoice Type Name  Net Sum Company Security Supplier Date Completed YearMonth     Category
0      710830     282.81           Invoice          282.810    asd5a      Abc       1/1/2018    2018-1       Postal
1      445800    4868.71           Invoice         3926.400   adc6ac      Def       1/1/2018    2018-1          R&D
2      710350     282.81           Invoice          282.810     fgn6      Ghi       2/9/2018    2018-2        Other
3      710510     282.81           Invoice          282.810       dg      jkl       2/9/2018    2018-2  Electricity
4      710630     841.59           Invoice          707.070  dfvbfbf      mno       3/2/2018    2018-3      Repairs
5      710610     841.59           Invoice          707.070     rrcv      pqr       3/2/2018    2018-3      Leasing
6      710810      12.14           Invoice           10.120    btbfd      stu       1/1/2019    2019-1    Telephone
7      704300   81517.60           Invoice        65740.000    dfbtt      vwx       1/1/2019    2019-1    Statutory
8      710510    2105.64           Invoice         1776.530  dfdftb5      dfb       2/9/2019    2019-2  Electricity
9      710510    2105.64           Invoice         1776.530  ebdfb5b      bcd       2/9/2019    2019-2  Electricity
10     710920      66.96           Invoice           54.000  dfrrt65      efg       3/2/2019    2019-3         Data
11     700330     239.47           Invoice          239.470  aae3a11      hij       3/2/2019    2019-3       Coffee
12        NaN        NaN               NaN        34979.665      NaN      NaN            NaN    2020-1          NaN
13        NaN        NaN               NaN         2059.340      NaN      NaN            NaN    2020-2          NaN
14        NaN        NaN               NaN          853.805      NaN      NaN            NaN    2020-3          NaN

备注:

  • 每月查找新年允许在滚动年份(例如从 2017 年 7 月到 2019 年 6 月)使用代码
  • 您可以用new_df = new_df.fillna('') 将NaN 替换为空字符串(或其他)

【讨论】:

  • 嘿 Serge,嘿 Serge,是否可以计算平均值而不是 sum ?平均3个月(我们在这里总结的相同月份)。我也更新了我的问题中的预期数据框以使其更加清晰。
  • 我已经尝试过了,但不知何故数字不正确,请参阅我上面显示的最终目标数据框和 2020-1 之后的数字,这不是我在这条线之后得到的。很清楚,平均值应该是 sum(jan2018)+sum(jan2019)/2 因为我在这里只考虑两个月。
  • 完美的解决方案和描述,非常感谢。
【解决方案2】:

对于简单的 3 年滚动平均值,请执行以下操作:

df1['Date Completed'] = pd.to_datetime(df1['Date Completed'])
df1['roll_3y_avg'] = df1.rolling(window='1096D', on='Date Completed', closed='right')['Net Sum Company'].mean()

【讨论】:

  • 谢谢,但这不是我想要的。
猜你喜欢
  • 2019-09-04
  • 2021-08-18
  • 2018-06-22
  • 2016-02-12
  • 2022-08-17
  • 2019-03-03
  • 2014-04-01
  • 2018-11-20
  • 1970-01-01
相关资源
最近更新 更多