提问人:azimm 提问时间:9/16/2023 最后编辑:Ben Bolkerazimm 更新时间:9/16/2023 访问量:53
在 R 中对 6000 万行数据运行 for 循环 - 有没有更快的方法?
Running a for loop in R on 60 million rows of data - is there a faster way?
问:
我目前正在 R 中运行一个 for 循环,该循环试图为数据集中的“行程”创建唯一 ID,但有时行程会在数据集中拆分为两行或多行。for 循环包含定义行程是仅由一行还是多行表示所需的逻辑。这意味着 for 循环需要查看它正在评估的当前行和上一行,评估条件语句,然后应用与前一行相同的 ID 或将值递增 1 以创建新 ID。
我还必须在 for 循环中添加一个特定的检查,该循环将第一行默认为值 1,因为没有上一行可以比较,并且如果没有此添加,我就会收到错误。
这在 100 行的测试数据集上运行良好,并为我提供了我想要的输出,但现在我在 6000 万行上运行它,到目前为止它已经运行了超过 24 小时。有没有办法加快这个过程并使其更快?我无法弄清楚如何将 lapply 或其他 apply 函数与这种条件复合体一起使用,但可能误解了这些函数的工作原理。我也不确定这是否会加快处理速度。另一种选择可能是将表拆分为单独的表并分块运行我的脚本,但感觉脚本应该只查看每一行及其前面的行,所以我不确定这是否真的可以节省时间(但会提供中间保存点的故障保护,以防我的服务器崩溃, 等)。
欢迎对此进行任何改进!
这是当前脚本:
Oct19Subset <- Oct19%>%
arrange(media_uuid, `Entry Date`) %>%
mutate(prev_mediaUUID = c(0, head(media_uuid, -1)))%>%
mutate(linked_trip_id = 1)
for (i in 1:nrow(Oct19Subset)){
if (i == 1) {
Oct19Subset$linked_trip_id[i] <- 1
} else {
if (Oct19Subset$`Ride Type`[i] == "B" |
Oct19Subset$media_uuid[i] != Oct19Subset$prev_mediaUUID[i]){
Oct19Subset$linked_trip_id[i] <- Oct19Subset$linked_trip_id[i-1] + 1
} else Oct19Subset$linked_trip_id[i] <- Oct19Subset$linked_trip_id[i-1]
}
}
答:
1赞
jblood94
9/16/2023
#1
试试这个:
system.time(
Oct19Subset <- Oct19%>%
arrange(media_uuid, `Entry Date`) %>%
mutate(prev_mediaUUID = c(media_uuid[1] - 1, head(media_uuid, -1)))%>%
mutate(linked_trip_id = cumsum(`Ride Type` == "B" | media_uuid != prev_mediaUUID))
)
#> user system elapsed
#> 0.74 0.14 0.87
数据:
library(dplyr)
N <- 6e6
Oct19 <- setNames(
data.frame(
sample(1e5, N, 1),
as.Date(sample(19000:19600, N, 1)),
sample(LETTERS, N, 1)
), c("media_uuid", "Entry Date", "Ride Type")
)
或者,如果其他地方不需要帮助程序列,可以跳过它:
Oct19Subset <- Oct19%>%
arrange(media_uuid, `Entry Date`) %>%
mutate(
linked_trip_id = cumsum(
`Ride Type` == "B" |
media_uuid != c(media_uuid[1] - 1, head(media_uuid, -1))
)
)
评论
0赞
azimm
9/16/2023
使用 cumsum 几乎可以立即完美地工作
评论
dput()
Oct19Subset
cumsum(media_uuid != prev_mediaUUID | Ride_type == "B")