使用 dplyr 计算数据框中的梯度

Calculating gradient in data frame using dplyr

我有一个数据集,其中包括卖家 ID,以及每年 电视总销量的 数量。此数据框的示例如下所示:

ID <- c(1006332,1010660,1010852,1012960,1012960,1012960,1012960,1012960,1013515,1013515,1013515,1013515,101351)
Sold_year <- c(2017,2016,2011,2011,2012,2013,2015,2016,2014,2015,2016,2018,2019)
n <- c(1,1,1,12,1,3,4,1,2,1,3,1,2)
data <- data.frame(ID,Sold_year,n)

        ID Sold_year  n
1  1006332      2017  1
2  1010660      2016  1
3  1010852      2011  1
4  1012960      2011 12
5  1012960      2012  1
6  1012960      2013  3
7  1012960      2015  4
8  1012960      2016  1
9  1013515      2014  2
10 1013515      2015  1
11 1013515      2016  3
12 1013515      2018  1
13 1013515      2019  2

我想做的事情:我想计算每个卖家销售电视的平均梯度。例如:对于卖家 1013515,我想做如下计算:

grad1 = (1-2)/(2015-2014)=-1
grad2 = (3-1)/(2016-2015)= 2
grad3 = (1-3)/(2018-2016)=-1
grad4 = (2-1)/(2019-2018)= 1

average= -1+2-1+1/(4)=0.25

另外,对于一年只卖过一台电视的卖家,我认为梯度为0,并且会加上一个惩罚,这是销售年份和2020年之间的差值。所以对于卖家 1006332 这个平均梯度是

0-(2020-2017)=-3

到目前为止我做了什么: 为了进行以下计算,我使用了一个 for 循环来每次遍历特定代理列表并计算梯度。 这种方法有效并给出了正确的结果,但是,它对于大型数据集来说很慢。 我在想也许有一种方法可以简单地通过 dplyr 和数据帧计算来完成。我正在考虑使用 lag 函数,这是我的建议:

test2 <- data %>% 
  group_by(ID) %>% 
  mutate(grad=(n-lag(n))/(Sold_year-lag(Sold_year)))

这段代码的结果是:

 1                    1006332      2017     1  NA  
 2                    1010660      2016     1  NA  
 3                    1010852      2011     1  NA  
 4                    1012960      2011    12  NA  
 5                    1012960      2012     1 -11  
 6                    1012960      2013     3   2  
 7                    1012960      2015     4   0.5
 8                    1012960      2016     1  -3  
 9                    1013515      2014     2  NA  
10                    1013515      2015     1  -1  
11                    1013515      2016     3   2  
12                    1013515      2018     1  -1  
13                    1013515      2019     2   1  

如你所见,成功为工作一年以上的卖家计算出梯度;但是,我不确定我应该如何计算最终的平均梯度以及我应该如何对那些工作一年的卖家(卖家:1006332、1010660 等)添加惩罚

预期的输出应该是这种形式:

                                      ID                       Ave_grad
1                                        1006332                      -3.00
2                                        1010660                      -4.00
3                                        1010852                      -9.00
4                                        1012960                      -2.87
5                                        1013515                       0.25

有什么建议或意见吗?

谢谢

我们可以在按'ID'分组后做一个if/else条件,即if行数(n())为1,然后减去'Sold_year' 与当前年份 (year(Sys.Date()) 或 else 将 'n' 的 difference 除以 'Sold_year' 的 difference 并取 mean

library(dplyr)
library(lubridate)
data %>%
    group_by(ID) %>%
    summarise(grad = if(n() == 1) (Sold_year - year(Sys.Date())) else  
         mean(diff(n)/diff(Sold_year)), .groups = 'drop')

-输出

# A tibble: 5 x 2
#       ID  grad
#    <dbl> <dbl>
#1 1006332 -3   
#2 1010660 -4   
#3 1010852 -9   
#4 1012960 -2.88
#5 1013515  0.25