【发布时间】:2021-12-10 06:26:18
【问题描述】:
我正在将旧代码库转换为 tidyverse,我注意到某个特定步骤的性能下降;因为我现在使用readr (read_delim) 来读取我的数据,所以我最终得到了tibble,而不是之前的基本 R data.frame (read.delim) — 这很好。
无论如何,在逐行比较中使用tibble 时,与常规data.frame 相比,计算时间大约减少了10 倍。
这是我的代码:
library(tidyverse)
# Data
df <- tribble(
~x_pos, ~y_pos,
0.0, 5.0,
NA, NA,
0.1, 0.9,
1.1, 1.5,
1.7, 2.0,
3.2, 1.0,
4.0, 1.5,
4.1, 5.0,
)
# Defining Regions of interest
roi_set_top <- list(
roi_list = list(
roi1 = list(
hit_name = "left",
x1 = 1.0,
y1 = 1.0,
x2 = 2.0,
y2 = 2.0
),
roi2 = list(
hit_name = "right",
x1 = 3.0,
y1 = 1.0,
x2 = 4.0,
y2 = 2.0
)
)
)
# ⚡️ UNCOMMENT THIS LINE this line to convert the `tibble` to a `data.frame` and source the file again
# df <- as.data.frame(df)
start.time <- Sys.time()
for (bench in 1:1000) {
roi_vector <- rep("NO EVAL", times = nrow(df))
# loop over rows
for (i in 1:nrow(df)) {
# loop over the aoilist
for (roi in roi_set_top$roi_list) {
# check if either x or y is NA (or both) if so return NA
if (is.na(df[i, "x_pos"]) || is.na(df[i, "y_pos"])) {
roi_vector[i] <- "No X/Y"
break
}
# check the hit area
if (df[i, "x_pos"] >= roi$x1 && df[i, "y_pos"] >= roi$y1 &&
df[i, "x_pos"] <= roi$x2 && df[i, "y_pos"] <= roi$y2) {
roi_vector[i] <- roi$hit_name
break
}
# Finally, if current row’s x and y is neither NA nor in hit range assign Outside ROI
roi_vector[i] <- "Outside ROI"
}
}
}
end.time <- Sys.time()
time.taken <- end.time - start.time
print(time.taken)
比较
当您按原样获取代码时,与使用 ⚡️ 取消注释行并将其从 tibble 转换为 data.frame 时相比,所需时间大约长 10 倍。
如果我能像这样提取data.farme 的向量,我可以恢复我的表现:x_pos <- df$x_pos; y_pos <- df$x_pos 并在循环中使用向量而不是 df。但是,我有一个基本问题
问题
为什么 tibble 在逐行比较中的执行速度比基础 R data.frame 慢?
作为最佳实践风格的后续行动;当只需要使用向量时,使用 df 似乎是一种不好的做法。因此,应该不断地遍历向量而不是 df 中的列?
【问题讨论】:
标签: r dataframe dplyr tidyverse tibble