使用 ifelse 循环添加新列
Loop to add new columns with ifelse
我想让我的代码更有效率,我有一个调查,我的数据如下:
survey <- data.frame(
x = c(1, 6, 2, 60, 75, 40, 27, 10),
y = c(100, 340, 670, 700, 450, 200, 136, 145))
#Two lists:
A <- c(3, 6, 7, 27, 40, 41)
t <- c(0.10, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16)
我所做的是创建新列,如下所示:
z <- ifelse(survey$x %in% A), 0, min(t))
for (i in t) {
survey[paste0("T",i)] <-z
survey[paste0("T",i)] <-ifelse (z > 0, i, z)
}
但是用那个代码需要一段时间,有没有更好的方法呢?
您可以为此使用 sapply
:
#just make your new cols with sapply
newcols <- sapply(t, function(i) ifelse (z > 0, i, z))
#add the names you wanted
colnames(newcols) <- paste0("T", seq_along(t))
#merge to your original survey data set
cbind(survey, newcols)
# x y T1 T2 T3 T4 T5 T6 T7
#1 1 100 0.1 0.11 0.12 0.13 0.14 0.15 0.16
#2 6 340 0.0 0.00 0.00 0.00 0.00 0.00 0.00
#3 2 670 0.1 0.11 0.12 0.13 0.14 0.15 0.16
#4 60 700 0.1 0.11 0.12 0.13 0.14 0.15 0.16
#5 75 450 0.1 0.11 0.12 0.13 0.14 0.15 0.16
#6 40 200 0.0 0.00 0.00 0.00 0.00 0.00 0.00
#7 27 136 0.0 0.00 0.00 0.00 0.00 0.00 0.00
#8 10 145 0.1 0.11 0.12 0.13 0.14 0.15 0.16
正如 OP 提到的执行速度,data.table
选项会更快
library(data.table)
i1 <- !survey$x %in% A
setDT(survey)[, paste0("T", t) := 0]
for(j in t) {
set(survey2, i = which(i1), j = paste0("T", j), value = j)
}
基准
set.seed(24)
survey1 <- data.frame(x = sample(survey$x, 1e7, replace = TRUE),
y = sample(survey$y, 1e7, replace = TRUE))
survey2 <- copy(survey1)
system.time({
survey1[paste0("T", t)] <- lapply(t, function(y) ifelse(survey1$x %in% A, 0, y))
})
# user system elapsed
# 8.20 2.75 11.03
system.time({
i1 <- !survey2$x %in% A
setDT(survey2)[, paste0("T", t) := 0]
for(j in t) {
set(survey2, i = which(i1), j = paste0("T", j), value = j)
}
})
# user system elapsed
# 0.97 0.31 1.28
使用矩阵乘法可能会更快。
dat <- cbind(survey, matrix(!survey$x %in% A) %*% t)
x y 1 2 3 4 5 6 7
1 1 100 0.1 0.11 0.12 0.13 0.14 0.15 0.16
2 6 340 0.0 0.00 0.00 0.00 0.00 0.00 0.00
3 2 670 0.1 0.11 0.12 0.13 0.14 0.15 0.16
4 60 700 0.1 0.11 0.12 0.13 0.14 0.15 0.16
5 75 450 0.1 0.11 0.12 0.13 0.14 0.15 0.16
6 40 200 0.0 0.00 0.00 0.00 0.00 0.00 0.00
7 27 136 0.0 0.00 0.00 0.00 0.00 0.00 0.00
8 10 145 0.1 0.11 0.12 0.13 0.14 0.15 0.16
这里,matrix(!survey$x %in% A)
根据survey$x的值是否存在于A中,构造一个TRUE和FALSE的nX1矩阵。这个结果是矩阵乘以(%*%
)t,它被视为 1Xn 矩阵。那么结果就是想要的输出。
如果需要,您可以使用 lyzander 答案中的代码在之后添加列名。
我想让我的代码更有效率,我有一个调查,我的数据如下:
survey <- data.frame(
x = c(1, 6, 2, 60, 75, 40, 27, 10),
y = c(100, 340, 670, 700, 450, 200, 136, 145))
#Two lists:
A <- c(3, 6, 7, 27, 40, 41)
t <- c(0.10, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16)
我所做的是创建新列,如下所示:
z <- ifelse(survey$x %in% A), 0, min(t))
for (i in t) {
survey[paste0("T",i)] <-z
survey[paste0("T",i)] <-ifelse (z > 0, i, z)
}
但是用那个代码需要一段时间,有没有更好的方法呢?
您可以为此使用 sapply
:
#just make your new cols with sapply
newcols <- sapply(t, function(i) ifelse (z > 0, i, z))
#add the names you wanted
colnames(newcols) <- paste0("T", seq_along(t))
#merge to your original survey data set
cbind(survey, newcols)
# x y T1 T2 T3 T4 T5 T6 T7
#1 1 100 0.1 0.11 0.12 0.13 0.14 0.15 0.16
#2 6 340 0.0 0.00 0.00 0.00 0.00 0.00 0.00
#3 2 670 0.1 0.11 0.12 0.13 0.14 0.15 0.16
#4 60 700 0.1 0.11 0.12 0.13 0.14 0.15 0.16
#5 75 450 0.1 0.11 0.12 0.13 0.14 0.15 0.16
#6 40 200 0.0 0.00 0.00 0.00 0.00 0.00 0.00
#7 27 136 0.0 0.00 0.00 0.00 0.00 0.00 0.00
#8 10 145 0.1 0.11 0.12 0.13 0.14 0.15 0.16
正如 OP 提到的执行速度,data.table
选项会更快
library(data.table)
i1 <- !survey$x %in% A
setDT(survey)[, paste0("T", t) := 0]
for(j in t) {
set(survey2, i = which(i1), j = paste0("T", j), value = j)
}
基准
set.seed(24)
survey1 <- data.frame(x = sample(survey$x, 1e7, replace = TRUE),
y = sample(survey$y, 1e7, replace = TRUE))
survey2 <- copy(survey1)
system.time({
survey1[paste0("T", t)] <- lapply(t, function(y) ifelse(survey1$x %in% A, 0, y))
})
# user system elapsed
# 8.20 2.75 11.03
system.time({
i1 <- !survey2$x %in% A
setDT(survey2)[, paste0("T", t) := 0]
for(j in t) {
set(survey2, i = which(i1), j = paste0("T", j), value = j)
}
})
# user system elapsed
# 0.97 0.31 1.28
使用矩阵乘法可能会更快。
dat <- cbind(survey, matrix(!survey$x %in% A) %*% t)
x y 1 2 3 4 5 6 7
1 1 100 0.1 0.11 0.12 0.13 0.14 0.15 0.16
2 6 340 0.0 0.00 0.00 0.00 0.00 0.00 0.00
3 2 670 0.1 0.11 0.12 0.13 0.14 0.15 0.16
4 60 700 0.1 0.11 0.12 0.13 0.14 0.15 0.16
5 75 450 0.1 0.11 0.12 0.13 0.14 0.15 0.16
6 40 200 0.0 0.00 0.00 0.00 0.00 0.00 0.00
7 27 136 0.0 0.00 0.00 0.00 0.00 0.00 0.00
8 10 145 0.1 0.11 0.12 0.13 0.14 0.15 0.16
这里,matrix(!survey$x %in% A)
根据survey$x的值是否存在于A中,构造一个TRUE和FALSE的nX1矩阵。这个结果是矩阵乘以(%*%
)t,它被视为 1Xn 矩阵。那么结果就是想要的输出。
如果需要,您可以使用 lyzander 答案中的代码在之后添加列名。