如何在R中将数据从一个数据帧有效地提取到另一个数据帧?

时间:2019-08-01 14:07:29

标签: r performance data.table

我有两个数据框。由整数向量组成的一个,例如:

set.seed(10)

# create
dt1 <- data.table(INT = sample(1:110000, 10000, replace = F))

# sort
dt1 <- dt1[order(INT),]

详细说明不同整数的类别的一个。例如:

# create
dt2 <- data.table(CAT = sample(c("A", "B", "C", "D", "E"), 1000, replace = T),
              INT_START = sample(1:100000, 1000, replace = F),
              INT_END = sample(1:100000, 1000, replace = F))

# ensure start <= end 
tmp1 <- subset(dt2, dt2$INT_END < dt2$INT_START)
colnames(tmp1) <- c("CAT", "INT_END", "INT_START")
tmp2 <- subset(dt2, dt2$INT_END >= dt2$INT_START)
dt2 <- rbind(tmp1, tmp2)
rm(tmp1, tmp2)

# sort
dt2 <- dt2[order(CAT, INT_START),]

我需要确定与每个整数关联的类别。我可以使用for循环来做到这一点,例如:

dt1$CAT <- NA
for (i in 1:nrow(dt1)){
  ann.ind <- which(dt2$INT_START <= dt1$INT[i] & dt2$INT_END >= dt1$INT[i])
  dt1$CAT[i] <- paste0(unique(dt2$CAT[ann.ind]), collapse = "")
  print(i)
}

但是,我需要将此方法应用于多个非常大的数据集,这太慢了。通过执行以下操作,我可以使用data.table到达那里:

test1 <- dt2[dt1, on=.(INT_START<=INT, INT_END>=INT), allow.cartesian = T]

然后格式化结果:

if (identical(test1$INT_END, test1$INT_START)){
  test1 <- test1[,c("INT_END", "CAT")]
  colnames(test1) <- c("INT", "CAT")
  test1 <- test1[!duplicated(test1),]
}

如何有效配置test1,以便每一行都有一个唯一的INT,并将所有相应的类别粘贴到CAT中(即for循环示例)?

NB。一些整数将没有类别,而某些整数将具有多个类别。

谢谢。

1 个答案:

答案 0 :(得分:0)

dt1 <- dt2[dt1, on=.(INT_START<=INT, INT_END>=INT), allow.cartesian = T]

if (identical(dt1$INT_END, dt1$INT_START)){
  dt1 <- dt1[,c("INT_END", "CAT")]
  colnames(dt1) <- c("INT", "CAT")
  dt1 <- dt1[!duplicated(dt1),]
}

dt1 <- dcast(dt1, INT ~ CAT, value.var = "CAT")
dt1[is.na(dt1)] <- ""

dt1 <- data.table(INT = dt1[,1],
                  CAT = apply(dt1[,2:ncol(dt1)], 1, paste0, collapse = ""))