【问题标题】:Rollmean based on conditionsRollmean 基于条件
【发布时间】:2017-02-20 16:19:15
【问题描述】:

基于下面的数据框,我想基于三个条件使用rollmean创建一个新列-b列中的值相互匹配,a列中要平均的最小值为2,我只想平均当前行下方的所有值。如果要平均的值的数量为 2 或更少,我想返回一个空白值。

我假设我必须使用应用函数来执行此操作,但我不确定从哪里开始。

a=c(1,2,3,4,1,2,3,4,1,2,3,4)
b=c("X","X","X","X","Y","Y","Y","Y","Z","Z","Z","Z")
df=as.data.frame(cbind(a,b))

我希望决赛桌看起来像:

Name    Value   Output
X        1         2.5
X        2         3
X        3  
X        4  
Y        1         2.5
Y        2         3
Y        3  
Y        4  
Z        1         2.5
Z        2         3
Z        3  
Z        4  

【问题讨论】:

  • 你能用上面的例子解释一下你的情况吗?例如,上面数据帧中的值 2.5 是如何出现在第一行的,或者为什么它在第三行是空白的?
  • 第 1 行的输出值是后面所有 name =X 行的平均值,也就是 1,2,3,4 的平均值。在第 2 行中,输出是 2、3、4 或 3 的平均值。在第三行中,没有足够数量的值进行平均(小于 3),因此输出不返回任何内容。

标签: r zoo


【解决方案1】:

一个简单的tidverse 解决方案。在每个组中,如果剩余的项目超过两个,则从当前索引 (row_number()) 到最终索引 (n()) 取平均值。

library(tidyverse)
df %>% 
  group_by(b) %>% 
  mutate(Output = map_dbl(row_number(), ~ifelse(n() - . < 3, NA, mean(a[.:n()]))))

数据

您创建数据的方式将b 强制转换为字符向量(因为cbind 生成了一个矩阵)。

简单使用:

a <- c(1,2,3,4,1,2,3,4,1,2,3,4)
b <- c("X","X","X","X","Y","Y","Y","Y","Z","Z","Z","Z")
df <- data.frame(a, b)

或者

df <- data.frame(a = 1:4, b = rep(c('X', 'Y', 'Z'), each = 4))

【讨论】:

  • 如果我想将同样的想法应用于更大的数据集,并采用 500 个项目的滚动平均值,新的最小值为 150,那么我知道我可以将
  • ~ifelse(n() - . &lt; 150, NA, mean(a[.:(. + 500)], na.rm = TRUE))~ifelse(n() - . &lt; 150, NA, mean(a[.:min(. + 500, n())])) 应该可以工作。
【解决方案2】:

注意问题中df的形成有错误,所以我们在下面进行了修改。我们可以像这样使用ave。没有使用任何包。

df <- data.frame(a, b)
fun <- function(x) if (length(x) <= 2) NA else rev(cumsum(rev(x)) / c(NA, NA, 3:length(x)))
transform(df, Output = ave(a, b, FUN = fun))

给予:

   a b Output
1  1 X    2.5
2  2 X    3.0
3  3 X     NA
4  4 X     NA
5  1 Y    2.5
6  2 Y    3.0
7  3 Y     NA
8  4 Y     NA
9  1 Z    2.5
10 2 Z    3.0
11 3 Z     NA
12 4 Z     NA

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-20
    • 2018-10-27
    • 2012-06-29
    • 2019-02-05
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多