【发布时间】:2020-01-01 23:58:06
【问题描述】:
我是 r 的新手,希望在加快以下“for 循环”代码方面得到一些帮助。
代码旨在根据 ROE 列按部门和月份为每一行创建一个百分位排名
我在 r 中复制一个 excel 电子表格,该电子表格使用 PERCENTRANK.INC 函数,并且 r 代码需要精确复制它。我已经研究了 r 中的选项来匹配这个函数、dplyr 方法等,但除了下面的循环之外,似乎没有一个能完全复制结果。
问题的症结在于,循环需要 30 分钟才能为数据框创建所有百分位等级(输入数据框中的总行数约为 90,000)。有没有人有任何提示来加快下面的循环?我已经阅读了该站点上的许多类似问题/答案,并尝试了许多方法,例如对循环顶部附近的子集语句进行调整,但只成功地进行了有限的改进。
输入文件“ROE_Quintiles”的详细信息
- 它由历史股票 ROE 值组成,按月计算
- 关键列是:
- Merge_Var4,这是股票所属的 Sector 的组合 和月份,例如汽车和零部件Dec-03
- ROE2 是代码获得百分位排名的列(按部门和月份)
- Merge_Var3 是股票、它所属的行业和 月,例如Ford Motor CoAutomobiles & ComponentsDec-03
- ROE2_percrank 是在结束时输出的百分等级 每次迭代
非常感谢您的帮助。
冲锋枪
我的r代码如下所示:
# Create dataframe to append to at the end of each iteration
ROE_Quintiles3 <- data.frame("Merge_Var3" = c('Temp'), "ROE2_percrank" = c(0.5))
End <- nrow(ROE_Quintiles)
system.time({
for(i in 1:End) {
Row <- ROE_Quintiles[i,]
Row_Value <- subset(Row, select=c(ROE2))
Row_Value2 <- mean(Row_Value$ROE2) # PercentRankArgument Value
Row_Sector_Month <- subset(Row, select=c(Merge_Var4))
Row_Sector_Month_Values <- subset(ROE_Quintiles, Merge_Var4==Row_Sector_Month$Merge_Var4, select=c(ROE2))
# Filter Number to values less than the row value
NumberLessThanArgument = subset(Row_Sector_Month_Values, ROE2 < Row_Value2)
# Filter Number to values greater than or equal to the row value
NumberGreaterThanOrEqualArgument = subset(Row_Sector_Month_Values, ROE2 >= Row_Value2)
# RankLower = the count of Numbers less than row value, and is used later for
# interpolation of ranks
RankLower <- nrow(NumberLessThanArgument)
# NumberLower = the largest Number < row value, used for interpolation
NumberLower <- ifelse(RankLower==0, Row_Value2, max(NumberLessThanArgument))
# NumberUpper = the smallest Number >= row value, used for interpolation
NumberUpper = min(NumberGreaterThanOrEqualArgument)
# PercentRankArgumentRank = the rank of row value over the Number table, which is
# just RankLower + 1. This is the same rank as NumberUpper in the Number table itself.
PercentRankArgumentRank = RankLower + 1
# InterpolationFraction = fraction that row value is from NumberLower to NumberUpper
InterpolationFraction <- ifelse(RankLower==0, 0, (Row_Value2 - NumberLower)/(NumberUpper - NumberLower))
# Calculate the interpolated rank
RankInterpolated = max(1, RankLower + InterpolationFraction * (PercentRankArgumentRank - RankLower))
# Get the count of Numbers
NumberCount = nrow(Row_Sector_Month_Values)
# Final PercentRank is (RankInterpolated - 1)/(NumberCount - 1)
PercentRankOutput = (RankInterpolated - 1)/(NumberCount - 1)
# Append to create main dataframe
Row_Output <- subset(Row, select=c(Merge_Var3))
Row_Output$ROE2_percrank <- PercentRankOutput
ROE_Quintiles3 <- rbind(ROE_Quintiles3, Row_Output)
}
})
ROE_Quintiles3 <- subset(ROE_Quintiles3, Merge_Var3 != 'Temp')
【问题讨论】:
-
你可能根本不需要
for loop。如果您能提供ROE_Quintiles的小示例数据,并说明您的预期结果,将更便于其他人提供帮助。 -
一个肮脏的技巧是简单地使用像 doParallel 这样的包进行多处理
-
这太宽泛了,主要是要求重写。您能否尝试一个包含数据的最小示例?
标签: r performance for-loop