【问题标题】:How to create a 'running total'-like function如何创建类似“运行总计”的函数
【发布时间】:2017-01-08 21:44:54
【问题描述】:

我想以运行总计的方式对向量/矩阵执行函数。

简单地说

  perform the function for each row 
    from the first row up and including the current one

我找到了运行总计的各种解决方案,基本上是用 cumsum 函数。cumsum1dplyrcumsum2

但是 mean 函数已经没有按照我寻找的方式工作。而且 rle 也只适用于整个向量。

例子

> df <- data.frame(value = df <- data.frame(value = c(1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1)))
> df$csum <- ave(df$value, FUN=cumsum)
> df$mean <- ave(df$value, FUN=mean)
> df
   value csum mean
1      1    1 0.45
2      0    1 0.45
3      0    1 0.45
4      1    2 0.45
5      0    2 0.45
6      0    2 0.45
7      0    2 0.45
8      0    2 0.45
9      0    2 0.45
10     0    2 0.45
11     1    3 0.45
12     1    4 0.45
13     0    4 0.45
14     1    5 0.45
15     0    5 0.45
16     1    6 0.45
17     1    7 0.45
18     0    7 0.45
19     1    8 0.45
20     1    9 0.45

但我想得到:

     value     csum     mean     run_mean
 1       1        1     0.45     1
 2       0        1     0.45     0,5
 3       0        1     0.45     0,333333333
 4       1        2     0.45     0,5
 5       0        2     0.45     0,4
 6       0        2     0.45     0,333333333
 7       0        2     0.45     0,285714286
 8       0        2     0.45     0,25
 9       0        2     0.45     0,222222222
10       0        2     0.45     0,2
11       1        3     0.45     0,272727273
12       1        4     0.45     0,333333333
13       0        4     0.45     0,307692308
14       1        5     0.45     0,357142857
15       0        5     0.45     0,333333333
16       1        6     0.45     0,375
17       1        7     0.45     0,411764706
18       0        7     0.45     0,388888889
19       1        8     0.45     0,421052632
20       1        9     0.45     0,45

现在我知道我可以使用cumsum 和除法来解决均值挑战。但我想要一个通用的方法来解决类似rle

> df$rle <- ave(df$value, FUN=rle)
> df
   value csum mean                             rle
1      1    1 0.45 1, 2, 1, 6, 2, 1, 1, 1, 2, 1, 2
2      0    1 0.45 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
3      0    1 0.45 1, 2, 1, 6, 2, 1, 1, 1, 2, 1, 2
4      1    2 0.45 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
5      0    2 0.45 1, 2, 1, 6, 2, 1, 1, 1, 2, 1, 2
6      0    2 0.45 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
7      0    2 0.45 1, 2, 1, 6, 2, 1, 1, 1, 2, 1, 2
8      0    2 0.45 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
9      0    2 0.45 1, 2, 1, 6, 2, 1, 1, 1, 2, 1, 2
10     0    2 0.45 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
11     1    3 0.45 1, 2, 1, 6, 2, 1, 1, 1, 2, 1, 2
12     1    4 0.45 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
13     0    4 0.45 1, 2, 1, 6, 2, 1, 1, 1, 2, 1, 2
14     1    5 0.45 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
15     0    5 0.45 1, 2, 1, 6, 2, 1, 1, 1, 2, 1, 2
16     1    6 0.45 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
17     1    7 0.45 1, 2, 1, 6, 2, 1, 1, 1, 2, 1, 2
18     0    7 0.45 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
19     1    8 0.45 1, 2, 1, 6, 2, 1, 1, 1, 2, 1, 2
20     1    9 0.45 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
> 

对新手有什么建议吗?

编辑:使示例可重现(常量而不是 sample

【问题讨论】:

  • 不确定 ave 调用应该做什么:它们用于不相交的类别,它们需要三个参数:对于请求的运行均值函数为什么不。 function(x) {cumsum(x)/(1:length(x) )}
  • 注意:请使用set.seed,以便我们根据您的预期输出检查我们的结果
  • @42:这就是我的意思,我知道我可以通过除法计算平均值。但这不是我所追求的。
  • 澄清:我追求的是通用函数,而不是mean 的解决方案。请参阅并采取rle 示例
  • 根据你想要做什么,你可以用累积的方式来制定计算,这样 f(1:(n+1)) = F(f(1:n), n+ 1) 然后简单地使用 apply 系列中的一个函数来应用 F.

标签: r


【解决方案1】:

你可以试试

df$run_mean <- cumsum(df$value)/seq_len(nrow(df))
#> head(df)
#  value csum mean  run_mean
#1     1    1 0.45 1.0000000
#2     0    1 0.45 0.5000000
#3     0    1 0.45 0.3333333
#4     1    2 0.45 0.5000000
#5     0    2 0.45 0.4000000
#6     0    2 0.45 0.3333333

基本上是value的累积总和除以行号。


正如@akrun 所指出的,dplyr 包提供了一个函数cummean() 来计算它。因此,替代方案可能是:

df$run_mean <- dplyr::cummean(df$value)

数据

df <- structure(list(value = c(1L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 
0L, 1L, 1L, 0L, 1L, 0L, 1L, 1L, 0L, 1L, 1L), csum = c(1L, 1L, 
1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 4L, 4L, 5L, 5L, 6L, 7L, 7L, 
8L, 9L), mean = c(0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 
0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 
0.45), run_mean = c(1, 0.5, 0.333333333333333, 0.5, 0.4, 0.333333333333333, 
0.285714285714286, 0.25, 0.222222222222222, 0.2, 0.272727272727273, 
0.333333333333333, 0.307692307692308, 0.357142857142857, 0.333333333333333, 
0.375, 0.411764705882353, 0.388888888888889, 0.421052631578947, 
0.45)), .Names = c("value", "csum", "mean", "run_mean"), row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", 
"14", "15", "16", "17", "18", "19", "20"), class = "data.frame")

【讨论】:

  • 感谢您指出这一点,@akrun。是的,我记得看过那个。
猜你喜欢
  • 2015-11-28
  • 2018-03-30
  • 1970-01-01
  • 2016-05-31
  • 1970-01-01
  • 2014-07-09
  • 2020-03-14
  • 2019-10-07
  • 2021-10-21
相关资源
最近更新 更多