我有两个相同维度的数据帧(d1
和d2
)。我希望有一个来自d1
的单元格值的新数据框,它满足d2
的单元格(例如d2==1
)中的某些条件。如何避免循环?
d1 <- data.frame(c1=c("a","b","c"), c2=c("d","e","f"), c3=c("g","h","i"))
d2 <- data.frame(c1=1:3, c2=4:6, c3=3:1)
输出将如下所示:
new.d3 <- data.frame(c1=c("a",NA,NA), c2=c(NA,NA,NA), c3=c(NA,NA,"i"))
(注意:如果d1
是数字-而不是-与apply(X = d2, MARGIN = c(1,2), function(x) as.numeric(x==1))
的乘积就可以了,方法)。
谢谢!
答案 0 :(得分:3)
获取问题中给出的输出的简单方法:
d3 <- d1
d3[d2 != 1] <- NA
d3
# c1 c2 c3
# 1 a <NA> <NA>
# 2 <NA> <NA> <NA>
# 3 <NA> <NA> i
这看起来不错,但我认为对于大型数据帧(相同的输出),这实际上要更快
as.data.frame(Map(function(x, y) replace(x, y != 1, NA), d1, d2))
使用purrr的想法相同:
purrr::map2_dfc(d1, d2, ~replace(.x, .y != 1, NA))
基准:
d1 <- d1[sample(nrow(d1), 1e6, T),]
d2 <- d2[sample(nrow(d2), 1e6, T),]
f1 <- function(d1, d2){
d1[d2 != 1] <- NA
d1
}
f2 <- function(d1, d2){
as.data.frame(Map(function(x, y) replace(x, y != 1, NA), d1, d2))
}
f3 <- function(d1, d2){
purrr::map2_dfc(d1, d2, ~replace(.x, .y != 1, NA))
}
microbenchmark::microbenchmark(
f1(d1, d2),
f2(d1, d2),
f3(d1, d2)
)
# Unit: milliseconds
# expr min lq mean median uq max neval cld
# f1(d1, d2) 118.83801 158.59201 224.86299 186.87136 223.33531 564.9671 100 b
# f2(d1, d2) 38.10416 41.78067 74.28742 70.25838 77.31785 347.4876 100 a
# f3(d1, d2) 38.15257 41.38867 81.59480 70.50125 80.58185 342.8283 100 a
答案 1 :(得分:2)
我们可以使用data.table
library(data.table)
setDT(d1)
d3 <- copy(d1)
setDT(d2)
for(j in names(d1)) set(d3, i = which(d2[[j]] != 1), j = j, value = NA_character_)
d3
# c1 c2 c3
#1: a <NA> <NA>
#2: <NA> <NA> <NA>
#3: <NA> <NA> i
只需检查@IceCreamToucan中提到的其他方法的效率(并使用1e6数据集,就可以与其他方法比较)
f4 <- function(d1, d2) {
setDT(d1)
d3 <- copy(d1)
setDT(d2);
for(j in names(d1)) set(d3, i = which(d2[[j]] != 1), j = j, value = NA_character_)
}
microbenchmark::microbenchmark(
f1(d1, d2),
f2(d1, d2),
f3(d1, d2), f4(d1, d2))
#Unit: milliseconds
# expr min lq mean median uq max neval
# f1(d1, d2) 56.35683 68.77735 83.53886 74.39981 81.84057 439.05273 100
# f2(d1, d2) 22.13963 28.12246 39.92593 35.85082 40.69185 88.36349 100
# f3(d1, d2) 21.54314 27.66579 39.97058 34.36608 42.29246 85.74994 100
# f4(d1, d2) 21.17695 28.51543 33.43449 33.89201 37.08036 52.61904 100