Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >有没有一种方法可以提高R中for循环的性能?

有没有一种方法可以提高R中for循环的性能?
EN

Stack Overflow用户
提问于 2020-08-11 10:59:41
回答 3查看 60关注 0票数 0

我有一个数据集,它的观测量略多于132万。我试图在dataset中添加一个"growth.factor“列,该列从另一个名为"cat.growth”的数据集( 44x8 )中设置一个给定的县值和分类。

我需要运行以下352次代码--更改县名和分类名--以获得我想要的结果(44个县,8个不同的分类):

代码语言:javascript
运行
AI代码解释
复制
parcel.data.1$growth.factor <- ifelse(parcel.data.1$classification == "Ag" & parcel.data.1$county == "Ada", 1 + cat.growth["Ada","Ag"], parcel.data.1$growth.factor)

如果我这样做,运行大约需要16.7秒。但是它需要352行代码。使用这个for循环,我可以在4行代码中实现相同的目标:

代码语言:javascript
运行
AI代码解释
复制
for (x in parcel.data.1) {
  for (y in parcel.data.1$classification) {
    parcel.data.1$growth.factor <- ifelse(parcel.data.1$classification == y & parcel.data.1$county == x, 1 + cat.growth[x,y], parcel.data.1$growth.factor)
  }}

但是当我运行它时,我甚至无法完成它( 12分钟后我就放弃了)。我尝试使用我的Mac中的所有核心,使用:

代码语言:javascript
运行
AI代码解释
复制
library(foreach)
library(doSNOW)
c1 <- makeCluster(8, type = "SOCK")
registerDoSNOW(c1)

但这没什么用。我看过所有关于慢循环的博客和其他帖子,但是我的代码只是一行,所以在其他建议中我没有看到任何适用于更快的东西。

任何帮助使这个循环在不到一分钟内运行将是非常感谢的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-08-11 12:27:51

正如其他人所指出的,您不应该使用循环。但你的问题似乎是“为什么这个循环要花这么长时间?”

答案是,您似乎正在遍历parcel.data.1$county的所有136万元素和parcel.data.1$classification的所有136万元素。这意味着您的循环正在计算ifelse() 1360000^2次数,而不是352次。

如果要使用循环,那么对每个列的唯一元素进行循环,这些元素由cat.growth的行名和列名提供。

代码语言:javascript
运行
AI代码解释
复制
for (x in rownames(cat.growth)) { # loop over counties
  for (y in colnames(cat.growth)) { # loop over classifications
    ...
  }
}

这个循环相当于352行代码的原始脚本,因此它应该有大约16秒的运行时间。

注意,如果您还不知道这两个向量的唯一元素,那么您可以使用unique()来找到它们。

票数 0
EN

Stack Overflow用户

发布于 2020-08-11 11:53:37

这似乎是创建联接的原因,而dplyr包正是您想要的。

我没有你的数据,但基于你的代码,我组装了一些简单的假数据,看起来像你的结构一样。

代码语言:javascript
运行
AI代码解释
复制
df1 <- data.frame(x = c("Ag", "Ag", "Be", "Be", "Mo", "Mo"),
                  y = c("A", "B", "A", "B", "A", "B"))
df2 <- data.frame(x = c("Ag", "Be", "Mo"),
                  A = c(1, 2, 3),
                  B = c(4, 5, 6))
library(dplyr)
library(tidyr)
df1 %>%
  inner_join(df2 %>% pivot_longer(cols = c(A, B), names_to = "y")) %>%
  mutate(value = value + 1)
Joining, by = c("x", "y")
   x y value
1 Ag A     2
2 Ag B     5
3 Be A     3
4 Be B     6
5 Mo A     4
6 Mo B     7
票数 0
EN

Stack Overflow用户

发布于 2020-08-11 11:56:59

这个循环可能不是最好的方法。一个备选方案可以是将cat.growth数据(44x8)重塑为具有县、分类和增长因子(即352x3)变量的data.frame,然后在此和原始数据帧上使用“合并”。

为了说明我的意思(基于我对您的数据的理解):

代码语言:javascript
运行
AI代码解释
复制
cat.growth <- as.data.frame(matrix(nrow = 44, ncol = 8,
                            dimnames = list(1:44, letters[1:8]),
                            data = rnorm(44*8)))

parcel.data <- data.frame(county = sample(1:44, 1e06, replace = TRUE),
                          classification = sample(letters[1:8], 1e06, replace = TRUE))

cat.growthL = reshape(cat.growth, direction = "long", 
                      idvar = "county", 
                      ids = rownames(cat.growth),
                      varying = 1:8, 
                      times = colnames(cat.growth),
                      timevar = "classification", 
                      v.names = "growth.factor")

parcel.data2 = merge(parcel.data, cat.growthL)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63364710

复制
相关文章

相似问题

添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档