在R中正确使用microbenchmark函数执行基准测试的技术问询
关于R中microbenchmark函数使用的正确性疑问
背景与现有代码实现
我正在学习如何在R中使用microbenchmark函数,为此模拟了不同规模的随机数据集:
# 加载所需包 library(lubridate) library(microbenchmark) library(forecast) my_list = list() index = c(100, 1000, 10000, 50000, 100000, 250000, 500000, 750000, 1000000) for (i in 1:length(index)) { my_data_i = data.frame(dates = sample(seq(as.Date('2010/01/01'), as.Date('2023/01/01'), by="day"), replace = TRUE, index[i]), visits = 1) my_list[[i]] = my_data_i }
随后定义了需要在每个数据集上重复执行的函数:
my_function = function(){ # 按周聚合数据 my_data_i_weekly <- aggregate(my_data_i$visits, list(week = week(my_data_i$dates), year = year(my_data_i$dates)), sum) # 转换为时间序列 my_data_i_ts <- ts(my_data_i_weekly$x, start = c(min(my_data_i_weekly$week), min(my_data_i_weekly$year)), frequency = 52) # 使用auto.arima拟合ARIMA模型 my_data_i_arima <- auto.arima(my_data_i_ts) }
过去我会手动计时每次迭代:
results = list() for (i in length(index)) { start.time_i <- Sys.time() my_data_i = my_list[[i]] print(replicate(n = 100, my_function())) end.time_i <- Sys.time() time.taken_i <- end.time_i - start.time_i results[[i]] = time.taken_i }
现在尝试用microbenchmark函数完成计时:
my_list2 = list() for (i in 1:length(index)) { my_data_i = my_list[[i]] res_i = microbenchmark(my_function(), times = 100) print(res_i) my_list2[[i]] = res_i }
需求与疑问
我的核心需求是:
- 在
my_list[[1]]上运行my_function()100次并记录耗时 - 在
my_list[[2]]上运行my_function()100次并记录耗时 - 以此类推,覆盖所有数据集
请问当前基于microbenchmark的实现方式是否正确?
另外,未来我希望绘制性能对比图:横轴为数据集规模,纵轴为运行耗时,用不同颜色的折线代表不同计算机的测试结果(类似一条红线、一条绿线的对比折线图)。
回答
你的当前代码在特定环境下可以运行,但存在明显的不规范问题,依赖全局变量会导致代码健壮性不足:
核心问题:函数依赖全局变量
my_function直接引用了全局环境中的my_data_i,虽然在循环中你每次会给my_data_i赋值,但这种写法容易引发意外错误(比如其他代码修改了全局的my_data_i),不符合R的函数式编程规范。正确的实现方式
修改my_function,让它接受数据作为参数,避免依赖全局变量:
my_function <- function(data){ # 按周聚合数据 data_weekly <- aggregate(data$visits, list(week = week(data$dates), year = year(data$dates)), sum) # 转换为时间序列 data_ts <- ts(data_weekly$x, start = c(min(data_weekly$week), min(data_weekly$year)), frequency = 52) # 使用auto.arima拟合ARIMA模型 data_arima <- auto.arima(data_ts) }
然后修改循环中的microbenchmark调用,传入对应数据集:
my_list2 = list() for (i in 1:length(index)){ current_data <- my_list[[i]] res_i <- microbenchmark(my_function(current_data), times = 100) print(res_i) my_list2[[i]] <- res_i }
这种写法更清晰、健壮,也便于后续维护和扩展。
- 关于性能绘图的建议
收集完my_list2中的结果后,可以提取每个数据集对应的耗时统计(比如均值、中位数),整理成包含「数据集规模」「不同计算机耗时」的数据框,之后使用ggplot2包即可绘制对比折线图,示例代码框架:
library(ggplot2) # 假设整理后的数据集名为perf_data ggplot(perf_data, aes(x = 数据集规模)) + geom_line(aes(y = 计算机1耗时均值, color = "计算机1")) + geom_line(aes(y = 计算机2耗时均值, color = "计算机2")) + labs(x = "数据集规模", y = "平均耗时(秒)", color = "设备") + theme_minimal()
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

