我有一个具有可变 RATE 的数据帧,该数据帧每隔几行都有一个 NA 值:
ID RATE
1 10
1 15
1 8
1 6
1 NA
1 10
1 20
1 NA
1 14
1 2
2 8
2 6
2 NA
在这些行上,我想添加一个变量mean_RATE和sd_RATE,对应于 NA 行之间所有行的平均值和 sd。此平均值和 sd 仅在具有相同 ID 的所有 RATES 上计算:
ID RATE mean_RATE sd_RATE
1 10
1 15
1 8
1 6
1 NA 9.75 3.86221
1 10
1 20
1 NA 15 7.071068
1 14
1 2
2 8
2 6
2 NA 7 1.414214
正如您在上面的所需输出中看到的那样,在任何均值或 sd 计算中都不会考虑 RATE 为 14 和 2 的行,因为下一个 NA 行具有不同的 ID。
有人可以帮助我有效地做到这一点吗?
我们可以用tidyverse
来做到这一点
library(dplyr)
df %>%
group_by(ID, grp = cumsum(lag(is.na(RATE), default = FALSE))) %>%
mutate(mean_RATE = mean(RATE, na.rm = TRUE), sd_RATE = sd(RATE, na.rm = TRUE)) %>%
mutate_at(vars(matches("_RATE")), funs(replace(., !is.na(RATE), NA)))
# A tibble: 13 x 5
# Groups: ID, grp [4]
# ID RATE grp mean_RATE sd_RATE
# <int> <int> <int> <dbl> <dbl>
# 1 1 10 0 NA NA
# 2 1 15 0 NA NA
# 3 1 8 0 NA NA
# 4 1 6 0 NA NA
# 5 1 NA 0 9.75 3.86
# 6 1 10 1 NA NA
# 7 1 20 1 NA NA
# 8 1 NA 1 15.0 7.07
# 9 1 14 2 NA NA
#10 1 2 2 NA NA
#11 2 8 2 NA NA
#12 2 6 2 NA NA
#13 2 NA 2 7.00 1.41
您可以
尝试使用函数ave
。
mutate(dat,new=ave(RATE,a<-cumsum(c(F,head(is.na(RATE),-1))),ID,
FUN = function(x)mean(x,na.rm=T)),
new=`is.na<-`(new,!is.na(RATE)),
sd=ave(RATE,a,ID,FUN=function(x)sd(x,na.rm=T)),
sd=`is.na<-`(sd,!is.na(RATE)))
ID RATE new sd
1 1 10 NA NA
2 1 15 NA NA
3 1 8 NA NA
4 1 6 NA NA
5 1 NA 9.75 5.629958
6 1 10 NA NA
7 1 20 NA NA
8 1 NA 15.00 5.629958
9 1 14 NA NA
10 1 2 NA NA
11 2 8 NA NA
12 2 6 NA NA
13 2 NA 7.00 1.414214