【发布时间】:2018-06-25 22:06:28
【问题描述】:
我一直在寻找关于这个的一些明确性,但找不到适用于我的案例的东西,我构建了一个与这个非常相似的 DF(但数据要多得多,总共超过一百万行)
Key1 <- c("A", "B", "C", "A", "C", "B", "B", "C", "A", "C")
Key2 <- c("A1", "B1", "C1", "A2", "C2", "B2", "B3", "C3", "A3", "C4")
NumVal <- c(2, 3, 1, 4, 6, 8, 2, 3, 1, 0)
DF1 <- as.data.frame(cbind(Key1, Key2, NumVal), stringsAsFactors = FALSE) %>% arrange(Key2)
ConsId <- c(1:10)
DF1 <- cbind(DF1, ConsId)
现在,我想做的是在数据框中添加 3 个新列(在现实生活中我需要 12 个,但为了在这个玩具示例中更加图形化,我们将使用 3 个)到数据框中,其中每个row 对应于 $NumVal 的值,具有相同的 $Key1 并且大于或等于 $ConsId 到每行中的值,并用 NA 填充剩余的空格,如果我不是很清楚,这是预期的结果:
Key1 Key2 NumVal ConsId V1 V2 V3
A A1 2 1 2 4 1
A A2 4 2 4 1 NA
A A3 1 3 1 NA NA
B B1 3 4 3 8 2
B B2 8 5 8 2 NA
B B3 2 6 2 NA NA
C C1 1 7 1 6 3
C C2 6 8 6 3 0
C C3 3 9 3 0 NA
C C4 0 10 0 NA NA
现在我正在使用 do.call(rbind),即使它工作得很好,对于超过 100 万行(大约 6 小时)的真实数据来说,它花费的时间太长了,我也尝试了bind_rows dplyr 函数,但它需要更长的时间,所以我坚持使用 do.call 选项,这是我正在使用的代码示例:
# Function
TranspNumVal <- function(i){
Id <- DF1[i, "Key1"]
IdCons <- DF1[i, "ConsId"]
myvect <- as.matrix(filter(DF1, Id == Key1, ConsId >= IdCons) %>% select(NumVal))
Result <- as.data.frame(t(myvect[1:3]))
return(Result)
}
# Applying the function to the entire data frame
DF2 <- do.call(rbind, lapply(1:NROW(DF1), function(i) TranspNumVal(i)))
DF3 <- cbind(DF1, DF2)
也许更改类导致代码效率低下,或者我只是没有找到更好的方法来矢量化我的问题(你不想知道嵌套循环需要多长时间),我'我对 R 相当陌生,刚刚开始玩 dplyr,所以我愿意接受有关如何优化我的代码的任何建议
【问题讨论】:
-
不要使用
as.data.frame(cbind,因为它会先创建一个矩阵,然后再创建一个data.frame,这样会出现类型问题。就做data.frame(Key1, Key2, .. -
当每个
Key1的行数超过三行时会发生什么情况,例如Key1 = C?Key1 = C的第一行中的新列无法存储所有NumVal值。在那种情况下你只保留前三个吗? -
谢谢,以后参考时会考虑的
-
是的@MauritsEvers 我们只保留前 3 个,我需要放弃其余的
标签: r