我想使用ifelse语句创建一个新变量,比如z。但是,其中一个返回值取决于矩阵的第i列。这是一个简单的例子
set.seed(1)
data <- data.frame(x = rnorm(10), y = rnorm(10), ind = rep(c(0, 1), 5))
m <- data.frame(matrix(rnorm(100), 10, 10))
z <- ifelse(data$ind == 1, data$x, sum(m[, i]))
我知道z的行不会运行,但它说明了我想做的事情。如果一个主题的ind变量等于0,那么我将z分配给m对应于主题i列的10个条目的总和。
我可以用ifelse做这个,还是需要for循环?我试图远离for循环,这就是为什么我首先尝试ifelse。
以下是z应该是什么样的:
z
[1] -1.3367324 0.1836433 1.3413668 1.5952808 4.5120996 -0.8204684 1.2736029
[8] 0.7383247 3.4748021 -0.3053884
谢谢!
答案 0 :(得分:4)
是的,您可以使用ifelse
和一行内容进行,非常接近您所写的内容:
z <- ifelse(data$ind == 0, colSums(m), data$x)
以下是R执行此语句时的作用:
data$ind == 0
,并将两个数字向量colSums(m)
和data$x
(data$ind == 0)
为True
,输出colSums(m)
;其中(data$ind == 0)
为False
,输出data$x
答案 1 :(得分:3)
或者我们可以使用算术
colSums(m)*(data$ind==0) + (data$ind==1)*data$x
# X1 X2 X3 X4 X5 X6 X7
#-1.3367324 0.1836433 1.3413668 1.5952808 4.5120996 -0.8204684 1.2736029
# X8 X9 X10
# 0.7383247 3.4748021 -0.3053884
答案 2 :(得分:2)
你可以用双线代替它:
z <- data$x
z[data$ind == 0] <- colSums(m[,data$ind == 0])
[1] -1.3367324 0.1836433 1.3413668 1.5952808 4.5120996 -0.8204684 1.2736029 0.7383247 3.4748021
[10] -0.3053884
更一般地说,您可以使用apply
函数。这通常比直接矢量化解决方案慢,如上所述。这是讽刺的:
sapply(1:nrow(data), function(x){ifelse(data$ind[x] == 1, data$x[x], sum(m[, x]))})
[1] -1.3367324 0.1836433 1.3413668 1.5952808 4.5120996 -0.8204684 1.2736029 0.7383247 3.4748021
[10] -0.3053884
基准:
microbenchmark::microbenchmark(
sapply = sapply(1:nrow(data), function(x){ifelse(data$ind[x] == 1, data$x[x], sum(m[, x]))}),
vectorised = {z <- data$x;
z[data$ind == 0] <- colSums(m[,data$ind == 0])})
Unit: microseconds
expr min lq mean median uq max neval cld
sapply 391.297 408.193 423.6525 412.4170 423.7450 853.249 100 b
vectorised 197.377 199.873 208.7701 202.5605 214.4645 284.545 100 a