Groupby,按月求和,用Python计算标准偏差除以平均值
对于Groupby,按月求和,用Python计算标准偏差除以平均值,python,pandas,dataframe,group-by,Python,Pandas,Dataframe,Group By,对于df: id Date ITEM_ID TYPE VALUE YearMonth 0 13710750 2019-07-01 SLM607 O 10 2019-07 1 13710760 2019-07-01 SLM607 O 10 2019-07 2 13710770 2019-07-03 SLM607 O 2 2019-07 3 13
df
:
id Date ITEM_ID TYPE VALUE YearMonth
0 13710750 2019-07-01 SLM607 O 10 2019-07
1 13710760 2019-07-01 SLM607 O 10 2019-07
2 13710770 2019-07-03 SLM607 O 2 2019-07
3 13710780 2019-09-03 SLM607 O 5 2019-09
4 13667449 2019-08-02 887643 O 7 2019-08
5 13667450 2019-08-02 792184 O 1 2019-08
6 13728171 2019-09-17 SLM607 I 1 2019-09
7 13667452 2019-08-02 794580 O 3 2019-08
可复制示例:
data = {
"id": [
13710750,
13710760,
13710770,
13710780,
13667449,
13667450,
13728171,
13667452,
],
"Date": [
"2019-07-01",
"2019-07-01",
"2019-07-03",
"2019-09-03",
"2019-08-02",
"2019-08-02",
"2019-09-17",
"2019-08-02",
],
"ITEM_ID": [
"SLM607",
"SLM607",
"SLM607",
"SLM607",
"887643",
"792184",
"SLM607",
"794580",
],
"TYPE": ["O", "O", "O", "O", "O", "O", "I", "O"],
"YearMonth": [
"2019-07",
"2019-07",
"2019-07",
"2019-09",
"2019-08",
"2019-08",
"2019-09",
"2019-08",
],
"VALUE": [10, 10, 2, 5, 7, 1, 1, 3],
}
df = pd.DataFrame(data)
我想将df
按ITEM_ID
分组,使用YearMonth
对每个月的VALUE
进行求和,如果没有一个月的数据,则为该月创建一行0
值。时间段应该是从2019-07
到2020-06
,即财政年度。然后我想计算每月总和值
的标准偏差除以平均值。因此,每个项目ID
都有一个该年的标准偏差/平均值的最终值
第一步,我是用
df.groupby(['ITEM_ID', 'YearMonth']).sum().reset_index()
计算每月的金额,但我不知道如何从这里继续下去。谢谢你的建议,谢谢
关于如何计算每个
项目的标准偏差的示例\u ID
例如,使用ITEM_ID==SLM607
Month Sum of VALUE
2019-07 22 (10 + 10 + 2)
2019-09 6 (5 + 1)
对于2019-07-01至2020-06-30的其他月份,我们假设每个月0
因此,ITEM_ID==SLM607
的标准偏差将是列表[22,6,0,0,0,0,0,0]
的标准偏差,该列表给出了以下结果:
np.std([22, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) = 6.155395104206463 (or 6.4291005073286 for sample std dev)
对原问题中造成的任何混乱表示歉意。我正试图用建议的解决方案来理解大小差异的原因。您的第一步是按对象+月份计算总和,但为了完整起见,我只在这里复制它(请注意,我只计算总和值,因为ID在数字上没有意义;如果您想保留它们,可以按它们分组): 现在您需要三个值:考虑的月数,然后是该跨度内每个项目的标准差和平均值。如果不同的对象在不同的持续时间内可用,这会变得有点棘手,因此我将继续使用更简单的情况,假设所有对象在相同的持续时间内可用,我将其称为
months=12
(您指定感兴趣的时间范围为一整年)
平均值和标准偏差的方程都假设我们知道正确的N(在你的例子中是12)。我们可以用0填充数据帧,以允许Pandas内置的mean
和std
方程工作,或者我们可以实现我们自己的函数,按需执行填充。后者听起来更简单
In [3]: months = 12
In [4]: def mean_over_months(data):
...: return np.mean(list(data) + [0] * (months - len(data)))
...:
In [5]: def std_over_months(data):
...: return np.std(list(data) + [0] * (months - len(data)))
...:
In [6]: by_month.groupby('ITEM_ID')['VALUE'].agg(mean_over_months)
Out[6]:
ITEM_ID
792184 0.083333
794580 0.250000
887643 0.583333
SLM607 2.333333
Name: VALUE, dtype: float64
现在只需执行所需的计算:
In [7]: item_means = by_month.groupby('ITEM_ID')['VALUE'].agg(mean_over_months)
In [8]: item_stds = by_month.groupby('ITEM_ID')['VALUE'].agg(std_over_months)
In [9]: item_stds / item_means
Out[9]:
ITEM_ID
792184 3.464102
794580 3.464102
887643 3.464102
SLM607 2.755329
Name: VALUE, dtype: float64
@Szymon Maszke感谢编辑只需一个小的加法,平均值可以通过
by_month.groupby(“ITEM_ID”)[“VALUE”].sum()/12
,在这种情况下不需要辅助函数。感谢斯奈德提供了漂亮的解决方案。这很有帮助。嗨,克里斯,谢谢你简洁的解决方案。我计算了一些“ITEM_ID”,结果似乎略有不同,你知道为什么吗?如果你使用numpy
计算标准偏差,那么答案将不同于我在解决方案中使用的pandas
。Pandas的groupby.std
函数使用一个自由度作为默认值,其中numpy.std
使用零作为默认值。我希望这有助于回答您的问题,您可以阅读pandas.DataFrame.groupby.std
和numpy.std
文档了解更多信息。
In [7]: item_means = by_month.groupby('ITEM_ID')['VALUE'].agg(mean_over_months)
In [8]: item_stds = by_month.groupby('ITEM_ID')['VALUE'].agg(std_over_months)
In [9]: item_stds / item_means
Out[9]:
ITEM_ID
792184 3.464102
794580 3.464102
887643 3.464102
SLM607 2.755329
Name: VALUE, dtype: float64
df = pd.DataFrame(data)
# convert date string to datetiem
df['Date'] = pd.to_datetime(df['Date'])
# create a date range for your fiscal year
dr = pd.date_range('2019-07-01', '2020-06-01', freq='M').to_period('M')
# groupby year, month and item id and then sum the value column
g = df.groupby([df['Date'].dt.to_period('M'), 'ITEM_ID'])['VALUE'].sum()
# reindex the grouped multiindex with your new fiscal year date range and your item ids
new_df = g.reindex(pd.MultiIndex.from_product([dr, g.index.levels[1]], names=['Date', 'ITEM_ID']), fill_value=0).to_frame()
# create a groupby object
new_g = new_df.groupby(level=1)['VALUE']
# std divided by the mean of the groupby object
new_g.std()/new_g.mean()
ITEM_ID
792184 3.316625
794580 3.316625
887643 3.316625
SLM607 2.631636
Name: VALUE, dtype: float64