特定值的累积平均值

时间:2017-10-07 06:14:40

标签: r cumulative-sum

我想仅在值> 0时计算累积平均值。如果我有一个向量:

v <- c(1, 3, 0, 3, 2, 0)

平均值是9/6 = 1.5,但是我只想在值> 0时取平均值,因此在这种情况下它将是9/4 = 2.25。但是这个平均值是整个集合。我希望在数据集构建和累积时进行平均。所以,最初会是:

1+3/2, 1+3+0/2, 1+3+0+3/3, 1+3+0+3+2/4, 1+3+0+3+2+0/4

我的数据集是9,000行,而且还在增长。我可以让cumsum工作并计算累积总和,但不是“成功”的累计平均值。

2 个答案:

答案 0 :(得分:6)

您可以通过将v的累计和除以逻辑向量v > 0的累积和来解决此问题:

v1 <- cumsum(v)/cumsum(v>0)

给出:

> v1
[1] 1.000000 2.000000 2.000000 2.333333 2.250000 2.250000

如果要省略第一个值:

v2 <- (cumsum(v)/cumsum(v>0))[-1]

给出:

> v2
[1] 2.000000 2.000000 2.333333 2.250000 2.250000

后者等于问题中指定的期望结果:

> ref <- c((1+3)/2, (1+3+0)/2, (1+3+0+3)/3, (1+3+0+3+2)/4, (1+3+0+3+2+0)/4)
> identical(v2, ref)
[1] TRUE

数据集中的实现:

# create an example dataset
df <- data.frame(rn = letters[seq_along(v)], v)

# calculate the 'succes-cummulative-mean'
library(dplyr)
df %>% 
  mutate(succes_cum_mean = cumsum(v)/cumsum(v>0))

给出:

  rn v succes_cum_mean
1  a 1        1.000000
2  b 3        2.000000
3  c 0        2.000000
4  d 3        2.333333
5  e 2        2.250000
6  f 0        2.250000

答案 1 :(得分:1)

dplyr包具有cummean功能。如果你只想要&gt; 0,为v>0选择v的值:

v <- c(1, 3, 0, 3, 2, 0)

dplyr::cummean(v[v>0])
#> [1] 1.000000 2.000000 2.333333 2.250000

如果您希望重复结果,可以使用动物园中的索引和帮助函数。

# Create a vector container for the result (here with NA values)
v_res <- v[NA]
# Fill cumsum where you want to calculate it (here v>0)
v_res[v>0] <- dplyr::cummean(v[v>0])
# Fill the gap with previous value
zoo::na.locf(v_res)
#> [1] 1.000000 2.000000 2.000000 2.333333 2.250000 2.250000

它也适用于v中的负值

v <- c(1, 3, 0, 3, -5, 2, 0, -6)
v_res <- v[NA]
v_res[v>0] <- dplyr::cummean(v[v>0])
zoo::na.locf(v_res)
#> [1] 1.000000 2.000000 2.000000 2.333333 2.333333 2.250000 2.250000 2.250000

您也可以使用tidyverse。如果您的解决方案可能有用 数据在data.frame中。

library(dplyr, warn.conflicts = F)
library(tidyr)

data <- data_frame(v = c(1, 3, 0, 3, 2, 0)) %>%
  tibble::rowid_to_column() 
res <- data %>%
  filter(v > 0) %>%
  mutate(cummean = cummean(v)) %>%
  right_join(data, by = c("rowid", "v")) %>%
  fill(cummean)
res
#> # A tibble: 6 x 3
#>   rowid     v  cummean
#>   <int> <dbl>    <dbl>
#> 1     1     1 1.000000
#> 2     2     3 2.000000
#> 3     3     0 2.000000
#> 4     4     3 2.333333
#> 5     5     2 2.250000
#> 6     6     0 2.250000
pull(res, cummean)[-1]
#> [1] 2.000000 2.000000 2.333333 2.250000 2.250000