我有四个列,其中包含最近4年的销售量。我想计算中位数,然后通过根据条件(中位数的-25%)排除列值来计算平均值。
df = df[['Date','ID','amount']] # df has daily data
df['dayofYear'] = df['Date'].dt.dayofyear
df['Year_Lag1']= df.groupby(['ID','dayofYear'])['amount'].transform(lambda x: x.shift(1))
df['Year_Lag2']= df.groupby(['ID','dayofYear'])['amount'].transform(lambda x: x.shift(2))
df['Year_Lag3']= df.groupby(['ID','dayofYear'])['amount'].transform(lambda x: x.shift(3))
df['Year_Lag4']= df.groupby(['ID','dayofYear'])['amount'].transform(lambda x: x.shift(4))
df['YearLag_median']= df[['Year_Lag1','Year_Lag2','Year_Lag3','Year_Lag4']].median(axis=1) #median amount on same date (is there a better way to calculate median by avoiding outliers)
如何通过避免四列中位数为中位数的+ 25%的值来计算平均值。
假设Year_Lag1 = 5000, Year_Lag2= 230, Year_Lag3=4500, Year_Lag4= 4300
。
如何通过避免使用Year_Lag2
值来计算平均值。
我希望对数据框中的所有行执行此操作。
(同样,如果有人可以通过避免离群值来提供更好的方法来计算中位数) 数据集[data具有1月2日和3月3日的值(2014、15、16、17、18)。 Year_Lag1(shift(1))具有1月2日和1月3日的上一年的值。 Year_Lag2(shift(2)的值是从去年到去年),依此类推。]
最后一行是我要忽略589.0以计算均值的示例。
[1]:https://i.stack.imgur.com/26Dvp.png enter code here
答案 0 :(得分:0)
如果您可以添加数据框以供参考,那将是很好的。尝试通过在今年生成随机日期,随机浮动金额和随机ID来生成df(如您在下面指定的那样)。我的DF的5行头看起来像这样:
df.head(5)
amount Date ID
0 93 2019-01-01 00:00:00.000000000 AAA
1 40 2019-01-03 08:43:38.181818181 AAA
2 47 2019-01-05 17:27:16.363636363 BBB
3 37 2019-01-08 02:10:54.545454545 CCC
4 13 2019-01-10 10:54:32.727272727 CCC
这是您的数据集的样子吗? 如果是这样,那么运行您提到的滞后命令似乎无法正常工作。当我运行它时,如下所示:
df['dayofYear'] = df['Date'].dt.dayofyear
df.head(5)
Date ID amount dayofYear
0 2019-01-01 00:00:00.000000000 AAA 93 1
1 2019-01-03 08:43:38.181818181 AAA 40 3
2 2019-01-05 17:27:16.363636363 BBB 47 5
3 2019-01-08 02:10:54.545454545 CCC 37 8
4 2019-01-10 10:54:32.727272727 CCC 13 10
df['Year_Lag1']= df.groupby(['ID','dayofYear'])['amount'].transform(lambda x: x.shift(1))
df.head(5)
Date ID amount dayofYear Year_Lag1
0 2019-01-01 00:00:00.000000000 AAA 93 1 NaN
1 2019-01-03 08:43:38.181818181 AAA 40 3 NaN
2 2019-01-05 17:27:16.363636363 BBB 47 5 NaN
3 2019-01-08 02:10:54.545454545 CCC 37 8 NaN
4 2019-01-10 10:54:32.727272727 CCC 13 10 NaN
确保头部不是唯一一个带有Nans的人。整个专栏都得到了nans。如果您可以修改原始帖子以包含df,则可以轻松回答问题。
答案 1 :(得分:0)
这是一个解决方案,我认为应该有一些更好的方法,但是仍然有效:
def calculateMean(row):
s = 0
n = 0
for i in range(4):
if ~np.isnan(row[i]) and abs(row[i] - row[-1]) < 0.25 * row[-1]:
s += row[i]
n += 1
return (s/n if n else np.nan)
df["YearLag_mean"] = df.loc[:, ['Year_Lag1','Year_Lag2','Year_Lag3','Year_Lag4', 'YearLag_median']]\
.apply(lambda row: calculateMean(row), axis=1)
输出:
Date ID amount dayofYear Year_Lag1 Year_Lag2 Year_Lag3 Year_Lag4 YearLag_median YearLag_mean
2258 2014-01-02 200 1778.0 2 NaN NaN NaN NaN NaN NaN
2259 2014-01-03 200 2149.0 3 NaN NaN NaN NaN NaN NaN
2623 2015-01-02 200 2057.0 2 1778.0 NaN NaN NaN 1778.0 1778.00
2624 2015-01-03 200 2401.0 3 2149.0 NaN NaN NaN 2149.0 2149.00
2988 2016-01-02 200 2315.0 2 2057.0 1778.0 NaN NaN 1917.5 1917.50
2989 2016-01-03 200 589.0 3 2401.0 2149.0 NaN NaN 2275.0 2275.00
3354 2017-01-02 200 1709.0 2 2315.0 2057.0 1778.0 NaN 2057.0 2050.00
3355 2017-01-03 200 1659.0 3 589.0 2401.0 2149.0 NaN 2149.0 2275.00
3719 2018-01-02 200 1991.0 2 1709.0 2315.0 2057.0 1778.0 1917.5 1964.75
3720 2018-01-03 200 1570.0 3 1659.0 589.0 2401.0 2149.0 1904.0 1904.00
如您所见,由于您的阈值,最后一行未使用589
,但也未使用2401
。
要除去异常值而不是使用中位数,可以查看IQR或Z得分,但是我不确定它在小数据上是否能很好地工作,可以尝试并改编或创建新函数。