如何使用另一个大型数据框的内容填充一个大型数据框而不使用R for循环索引?

时间:2017-06-23 15:31:22

标签: r dataframe indexing

我有两个大的数据帧,A(~25,000行)和B(~275,000行),我需要使用B的内容填充A.我是R的新手,但我之前用Python编写过在pandas中使用for循环和索引可以合理地快速完成这种事情。但是由于在R中使用数据帧索引的循环非常缓慢,因此我编写的方法需要数天才能运行。任何人都知道如何更有效地完成以下任务?

IDs <- c(1,2,3,4,5,6,7,8,9,10)
description1 <- c(NA,NA,NA,NA,NA,NA,NA,NA,NA,NA)
description2 <- c(NA,NA,NA,NA,NA,NA,NA,NA,NA,NA)
description3 <- c(NA,NA,NA,NA,NA,NA,NA,NA,NA,NA)

descriptions <- c('description1','description3','description3','description1','description1','description2','description1','description3','description2','description2')
values <- c(100,200,300,400,500,600,700,800,900,1000)

A <- data.frame(IDs,description1,description2,description3)
B <- data.frame(IDs,descriptions,values)

for (k in 1:nrow(B)){
  for (y in 1:nrow(A)){
    col_index <- which(names(A) == B[k,2])
    column_name <- names(A)[col_index]
    ID_A <- A[y,1]
    ID_B <- B[k,1]
    descriptionA <- A[y,4]
    descriptionB <- B[k,2]
    if ((ID_A == ID_B) && (descriptionB == column_name)){
      A[y,col_index] <- B[k,3]
    }
  }
}

希望这很简单,我是个白痴。提前谢谢。

2 个答案:

答案 0 :(得分:1)

使用reshape包中的dcast,您实际上只需reshape2数据:

dcast(B, IDs ~ descriptions)

   IDs description1 description2 description3
1    1          100           NA           NA
2    2           NA           NA          200
3    3           NA           NA          300
4    4          400           NA           NA
5    5          500           NA           NA
6    6           NA          600           NA
7    7          700           NA           NA
8    8           NA           NA          800
9    9           NA          900           NA
10  10           NA         1000           NA

答案 1 :(得分:0)

OP表示由于问题规模,处理速度至关重要。

现在,dcast包以及reshape2包中提供了data.table。后者claims:

  

dcast.data.tablereshape2::dcast的更快版本,但是   对于data.table s。更重要的是,它能够非常好地处理   与内存使用相比,大数据非常有效   reshape2::dcast

所以,我想知道哪个版本对于data.frame A中的25.000行的给定问题大小(这是唯一IDs的数量)和data.frame {中的275.000行会更快。 {1}}。

创建基准数据

B

由于n_ID <- 25000L n_rows_B <- 275000L n_desc_per_ID <- round(n_rows_B / n_ID) descriptions <- sprintf("d%02i", seq_len(2L * n_desc_per_ID)) # set.seed() is required for reproducible data set.seed(123L) B_DF <- data.frame(IDs = rep(1:n_ID, each = n_desc_per_ID), d = as.vector(replicate(n_ID, sample(descriptions, n_desc_per_ID))), v = rpois(n_rows_B, 50)) B_DT <- data.table::data.table(B_DF) 中{1}}中的行数是B中唯一IDs的11倍,因此每个A 11个样本会从22个IDs中随机挑选出来}。请注意,变量名称已缩写,以便以后以宽格式保存屏幕空间。

descriptions如下所示

B

基准

对于基准测试,使用 IDs d v 1: 1 d07 43 2: 1 d17 36 3: 1 d09 49 4: 1 d21 52 5: 1 d19 50 --- 274996: 25000 d09 47 274997: 25000 d18 46 274998: 25000 d17 47 274999: 25000 d14 64 275000: 25000 d02 57 包:

microbenchmark
bm <- microbenchmark::microbenchmark(
  reshape2 = 
    res1 <- reshape2::dcast(B_DF, IDs ~ d, value.var = "v"),
  datatable = 
    res2 <- data.table::dcast(B_DT, IDs ~ d, value.var = "v"),
  times = 100L
)
bm

对于给定的问题,大小Unit: milliseconds expr min lq mean median uq max neval reshape2 69.57883 72.90287 84.61567 84.45119 86.10444 198.6079 100 datatable 34.66349 36.23196 39.80785 39.67117 40.37139 168.9877 100 确实是dcast.data.table的两倍。但是,问题大小仍然很小,绝对运行时间可以忽略不计。增加问题大小时,差异会变得更明显。对于reshape2::dcast中2.7 M行的问题,运行时间为1.2秒至0.4秒。