【问题标题】:Optimizing a for loop to run faster [duplicate]优化for循环以更快地运行[重复]
【发布时间】:2020-06-05 07:26:15
【问题描述】:

我正在处理一个包含超过 300 万个观测值的数据集。这个数据集包括超过 770,000 个我感兴趣的唯一 ID。数据包括有关这些 ID 的描述性信息。挑战在于这些唯一 ID 包含非唯一重复项,这意味着我需要找到一种方法来整合数据。

经过深思熟虑,我决定对数据集中的每个 ID 采取每列的模式。输出为每个 id 的每列提供了最常见的值。通过采用最常见的值,我可以将非唯一重复项合并到每个 id 的一行中。

问题:为此,我在 for 循环中迭代了超过 770,000 个唯一 ID。我想使用尽可能高效的代码,因为我一直在使用的 for 循环需要几天时间才能完成。

鉴于我提供的代码,有没有办法优化代码,使用并行处理,或者其他方式更有效地完成任务?

可重现的代码:

ID <- c(1,2,2,3,3,3)
x1 <- c("A", "B", "B","C", "C", "C")
x2 <- c("alpha", "bravo", "bravo", "charlie", "charlie2", "charlie2")
x3 <- c("apple", "banana", "banana", "plum1", "plum1", "plum")

df <- data.frame(ID, x1, x2, x3)

#Mode Function
getmode <- function(v) {
  uniqv <- unique(v)
  uniqv[which.max(tabulate(match(v, uniqv)))]
}

library(reshape2)

#Takes the mode for every column
mode_row <- function(dat){
  x <- setNames(as.data.frame(apply(dat, 2, getmode)), c("value"))
  x$variable <- rownames(x); rownames(x) <- NULL
  mode_row <- reshape2::dcast(x, . ~ variable, value.var = "value")
  mode_row$. <- NULL
  return(mode_row)
}

#Take the mode of each row to account for duplicate donors
df2 <- NULL
for(i in unique(df$ID)){
  df2 <- rbind(df2, mode_row(subset(df, ID == i)))
  #message(i)

}

df2

预期输出:

  ID x1       x2      x3
1  1  A    alpha   apple
2  2  B    bravo banana
3  3  C charlie2   plum1

【问题讨论】:

  • 我的直接反应是“不要使用for 循环”。使用分组处理(例如在 base R 或 tidyverse 中获得相同的结果。这将更加高效,并提供更紧凑和可读的代码。请发布您的预期输出。

标签: r for-loop optimization parallel-processing apply


【解决方案1】:

base R 中提供了分组函数,dplyrdata.table

基础R:

aggregate(.~ID, df, getmode)

#  ID x1       x2      x3
#1  1  A    alpha   apple
#2  2  B    bravo  banana
#3  3  C charlie2   plum1

dplyr

library(dplyr)
df %>% group_by(ID) %>% summarise(across(x1:x3, getmode))
#Use summarise_at in older version of dplyr
#df %>% group_by(ID) %>% summarise_at(vars(x1:x3), getmode)

data.table

library(data.table)
setDT(df)[, lapply(.SD, getmode), ID, .SDcols = x1:x3]

【讨论】:

  • 你们都是最棒的。在这里,我整天(和昨晚)都在等待 for 循环完成,您可以在不到一秒钟的时间内完成聚合函数并完成工作,哈哈,谢谢一百万!!
  • 聚合函数在应用于数据时生成数字变量,而在我较大的数据框中仅生成前 9 行?
  • 数值变量可能是因为你有数据作为因素?转换成字符再试一次?
  • 不,我转换为字符,但遗憾的是仍然得到了数值。但是,data.table 示例完美地显示在我的真实数据集上,因此我非常感激!
  • 可能这会起作用然后aggregate(cbind(x1, x2, x3)~ID, df, getmode)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-03
  • 1970-01-01
  • 2021-10-27
  • 1970-01-01
  • 2019-07-03
  • 2021-11-10
  • 1970-01-01
相关资源
最近更新 更多