我无法在任何地方找到答案.
我想计算基于行的平均值的数据帧的新变量.
例如:
data <- data.frame(id=c(101,102,103), a=c(1,2,3), b=c(2,2,2), c=c(3,3,3))
Run Code Online (Sandbox Code Playgroud)
我想使用mutate来创建变量d,它是a,b和c的意思.我希望能够通过选择d = mean(a,b,c)的方式来实现这一点,并且我还需要使用变量范围(例如dplyr)d = mean(a:c).
而且当然
mutate(data, c=mean(a,b))
Run Code Online (Sandbox Code Playgroud)
要么
mutate(data, c=rowMeans(a,b))
Run Code Online (Sandbox Code Playgroud)
不起作用.
你能给我一些小费吗?
问候
Mat*_*rde 28
您正在寻找
data %>%
rowwise() %>%
mutate(c=mean(c(a,b)))
# id a b c
# (dbl) (dbl) (dbl) (dbl)
# 1 101 1 2 1.5
# 2 102 2 2 2.0
# 3 103 3 2 2.5
Run Code Online (Sandbox Code Playgroud)
要么
library(purrr)
data %>%
rowwise() %>%
mutate(c=lift_vd(mean)(a,b))
Run Code Online (Sandbox Code Playgroud)
Kon*_*lph 13
dplyr非常适合对这类数据进行操作,因为它假设数据格式整洁,并且 - 对于有问题的问题 - 您的数据是不整洁的.
你当然可以先整理一下:
tidy_data = tidyr::gather(data, name, value, -id)
Run Code Online (Sandbox Code Playgroud)
看起来像这样:
id name value
1 101 a 1
2 102 a 2
3 103 a 3
4 101 b 2
5 102 b 2
6 103 b 2
…
Run Code Online (Sandbox Code Playgroud)
然后:
tidy_data %>% group_by(id) %>% summarize(mean = mean(value))
Run Code Online (Sandbox Code Playgroud)
name mean
(fctr) (dbl)
1 a 2
2 b 2
3 c 3
Run Code Online (Sandbox Code Playgroud)
当然,这会丢弃原始数据.您可以使用mutate
而不是summarize
避免这种情况.最后,您可以再次整理数据:
tidy_data %>%
group_by(id) %>%
mutate(mean = mean(value)) %>%
tidyr::spread(name, value)
Run Code Online (Sandbox Code Playgroud)
id mean a b c
(dbl) (dbl) (dbl) (dbl) (dbl)
1 101 2.000000 1 2 3
2 102 2.333333 2 2 3
3 103 2.666667 3 2 3
Run Code Online (Sandbox Code Playgroud)
或者,您可以汇总,然后将结果与原始表合并:
tidy_data %>%
group_by(id) %>%
summarize(mean = mean(value)) %>%
inner_join(data, by = 'id')
Run Code Online (Sandbox Code Playgroud)
在任何一种情况下结果都是相同的.我在概念上更喜欢第二种变体.
我认为建议使用data.frame
或切片的答案.
是最好的,但可以做得更简单,更像这样:
data %>% mutate(c = rowMeans(select(., a,b)))
Run Code Online (Sandbox Code Playgroud)
或者,如果您想避免.
,则有两个输入到您的管道的惩罚:
data %>% mutate(c = rowMeans(select(data, a,b)))
Run Code Online (Sandbox Code Playgroud)
我认为这是 dplyr 式的方式。首先,我创建一个函数:
my_rowmeans = function(...) Reduce(`+`, list(...))/length(list(...))
Run Code Online (Sandbox Code Playgroud)
然后,它可以在 mutate 中使用:
data %>% mutate(rms = my_rowmeans(a, b))
# id a b c rms
# 1 101 1 2 3 1.5
# 2 102 2 2 3 2.0
# 3 103 3 2 3 2.5
# or
data %>% mutate(rms = my_rowmeans(a, b, c))
# id a b c rms
# 1 101 1 2 3 2.000000
# 2 102 2 2 3 2.333333
# 3 103 3 2 3 2.666667
Run Code Online (Sandbox Code Playgroud)
为了处理 的可能性NAs
,必须对该函数进行丑化:
my_rowmeans = function(..., na.rm=TRUE){
x =
if (na.rm) lapply(list(...), function(x) replace(x, is.na(x), as(0, class(x))))
else list(...)
d = Reduce(function(x,y) x+!is.na(y), list(...), init=0)
Reduce(`+`, x)/d
}
# alternately...
my_rowmeans2 = function(..., na.rm=TRUE) rowMeans(cbind(...), na.rm=na.rm)
# new example
data$b[2] <- NA
data %>% mutate(rms = my_rowmeans(a,b,na.rm=FALSE))
id a b c rms
1 101 1 2 3 1.5
2 102 2 NA 3 NA
3 103 3 2 3 2.5
data %>% mutate(rms = my_rowmeans(a,b))
id a b c rms
1 101 1 2 3 1.5
2 102 2 NA 3 2.0
3 103 3 2 3 2.5
Run Code Online (Sandbox Code Playgroud)
的缺点my_rowmeans2
是它强制为矩阵。不过,我不确定这是否总是比Reduce
方法慢。
很少代码的另一个简单可能性是:
data %>%
mutate(c= rowMeans(data.frame(a,b)))
# id a b c
# 1 101 1 2 1.5
# 2 102 2 2 2.0
# 3 103 3 2 2.5
Run Code Online (Sandbox Code Playgroud)
由于rowMeans需要类似矩阵或data.frame的内容,因此可以使用data.frame(var1, var2, ...)
代替c(var1, var2, ...)
。如果您的数据中包含NA,则需要告诉R怎么做,例如删除它们:rowMeans(data.frame(a,b), na.rm=TRUE)
还有另外两种方法,如果您具有要汇总的列的数字位置或矢量名称,则很有用:
data %>% mutate(d = rowMeans(.[, 2:4]))
Run Code Online (Sandbox Code Playgroud)
要么
data %>% mutate(d = rowMeans(.[, c("a","b","c")]))
Run Code Online (Sandbox Code Playgroud)