在R中合并来自两个相同维度数据帧的信息

时间:2019-09-19 16:32:39

标签: r dataframe

我有两个相同维度的数据帧(d1d2)。我希望有一个来自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))的乘积就可以了,方法)。

谢谢!

2 个答案:

答案 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