【发布时间】:2014-02-24 02:53:29
【问题描述】:
我已将一些脚本从运行 OS X 10.6.8、4GB Ram 和 2.53GHz Core 2 Duo 处理器(大约 2008 年)的旧 iMac 迁移到运行 Windows Server 2008、64 位的新虚拟 AWS 机器配备 15GB 内存。尽管如此,以下代码在新的 Windows 机器上运行的时间是原来的 4 倍。
我已经更改了一些周围的代码,但这部分是瓶颈,是相同的。输入变量(unique_dates、summary_data、in_data)在两台机器之间也具有相似的大小。
在 Windows 机器上,每个 date 循环大约需要 30 秒,而之前在 Mac 上需要 5 秒。
任何关于如何加快速度的建议将不胜感激。
* 更新 *
从正在制作的 cmets 中,我得到的印象是,有一种更快的方法可以做到这一点,而无需我将原始问题呈现为有争议的循环。
我正在努力实现以下目标: 我有许多公司的时间序列数据。对于每个日期,每家公司都有第 1 个月、第 3 个月、第 6 个月、第 12 个月、第 18 个月和第 24 个月的回报。每个公司也被分配到一个组(分位数)。对于每个日期,我想计算每个分位数的平均和中位数 1mth、3mth、6mth 等回报。
然后将结果存储在预先分配的summary_data 数据帧中。
实际数据有 343 个日期,每个日期有 500 家公司,分位数有 25 家公司。最慢的部分是ss_in_data <- subset(in_data, ...),而其余部分总共大约需要 0.02 秒。
我对 R 还很陌生,但在 MYSQL 中,我可以很简单地使用 MEAN 和 GROUP BY DATE, FRACTILE 来计算。在 R 中有类似的方法吗?
再次感谢大家的帮助。
我当前的代码在示例数据下方:
# In this sample data there are 12 companies, 3 dates. Each company is
# assigned to 1 of 3 fractiles
# Consequently there are 4 companies in each fractile.
# Create input data
date1 <- as.Date(as.character('2010-01-31'),"%Y-%m-%d")
date2 <- as.Date(as.character('2010-02-28'),"%Y-%m-%d")
date3 <- as.Date(as.character('2010-03-31'),"%Y-%m-%d")
dates <- c(rep(date1,12),rep(date2,12),rep(date3,12))
coys <- rep(c('A','B','C','D','E','F','G','H','I','J','K','L'),3)
ret_3mth <- rep(seq(0.1, by=0.2, length.out = 12),3)
ret_6mth <- rep(seq(0.2, by=0.2, length.out = 12),3)
ret_12mth <- rep(seq(0.3, by=0.2, length.out = 12),3)
fractiles <- rep(rep(c(1,2,3),4),3)
in_data <- data.frame(dates, coys, ret_3mth, ret_6mth, ret_12mth, fractiles)
# Initialise summary data frame
dates <- c(rep(date1,3),rep(date2,3),rep(date3,3))
fractiles <- rep(c(1,2,3),3)
mean_3mth <- rep(NA,9)
mean_6mth <- rep(NA,9)
mean_12mth <- rep(NA,9)
summary <- data.frame(dates, fractiles, mean_3mth, mean_6mth, mean_12mth)
# Other variables
unique_dates <- unique(dates)
num_fract_curr <- 3
当前方法:
for (date in unique_dates) {
# Only write to screen ever x loops (as set by write_line_freq)
if (counter%%write_line_freq == 0) {
writeLines(paste(run_name,' : Summary calcs ROCE ',roce, ' Date: ',as.Date(date, origin='1970-01-01'),
' ',counter,':',num_dates,' Time: ',format.timediff(start_time),sep=''))
}
counter <- counter + 1
for(i in 1:num_fract_curr) {
# Create subsets to speed up processing
ss_summary_data <- subset(summary_data, date_base == as.Date(date, origin='1970-01-01') & summary_data[summary_data_fractile] == i)
ss_in_data <- subset(in_data, date_base == as.Date(date, origin='1970-01-01') & in_data[in_data_fractile] == i)
# Causes error if ss_in_data is empty
if (nrow(ss_in_data) > 0) {
ss_summary_data$mean1mth <- mean(ss_in_data$ret_1mth, na.rm = TRUE)
ss_summary_data$median1mth <- median(ss_in_data$ret_1mth, na.rm = TRUE)
ss_summary_data$mean3mth <- mean(ss_in_data$ret_3mth, na.rm = TRUE)
ss_summary_data$median3mth <- median(ss_in_data$ret_3mth, na.rm = TRUE)
ss_summary_data$mean6mth <- mean(ss_in_data$ret_6mth, na.rm = TRUE)
ss_summary_data$median6mth <- median(ss_in_data$ret_6mth, na.rm = TRUE)
ss_summary_data$mean12mth <- mean(ss_in_data$ret_12mth, na.rm = TRUE)
ss_summary_data$median12mth <- median(ss_in_data$ret_12mth, na.rm = TRUE)
ss_summary_data$mean18mth <- mean(ss_in_data$ret_18mth, na.rm = TRUE)
ss_summary_data$median18mth <- median(ss_in_data$ret_18mth, na.rm = TRUE)
ss_summary_data$mean24mth <- mean(ss_in_data$ret_24mth, na.rm = TRUE)
ss_summary_data$median24mth <- median(ss_in_data$ret_24mth, na.rm = TRUE)
# Save the updated summary data back into the 'summary_data' data frame
summary_data[(summary_data$date == date) & (summary_data[summary_data_fractile] == i),] <- ss_summary_data
}
}
}
【问题讨论】:
-
我假设您将
ss_summary_data预分配到正确的大小?如果没有,这是一个明显的改进,将速度提高几个数量级。 -
@PaulHiemstra 不,我根本没有预先分配
ss_summary_data。作为data.frame,我没有意识到你应该甚至可以这样做。第一次引用或定义它是在您看到的代码中。与ss_in_data相同,在此代码中定义。他们都应该预先分配吗?不过它们并不大,最多 50 行。 -
好的,最多 50 行听起来不会造成瓶颈。在 R 中,按顺序增长一个对象是出了名的慢,但当然只用于构建一个有 50 行的更大的对象。
-
没有按顺序构建。
ss_summary_data在每个循环中被重新创建/覆盖为summary_data的子集,然后写回到已经创建的summary_data,因此它的大小不会改变。 -
从代码中很难准确地理解你要在那里做什么,但如果我没有错过什么,你不应该需要
for循环。看起来您正在尝试重新发明“拆分-应用-组合”方法。查看包 plyr、dplyr 或 data.table。
标签: windows r performance macos