我的日期集有超过132万个观察值。我正在尝试向数据集中添加一个“ growth.factor”列,以给定县和来自另一个名为“ cat.growth”的数据集(44x8)的分类来设置特定值。
我需要运行以下代码352次-更改县和类别名称--以得到我想要的结果(44个县,8个不同的类别):
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行代码中实现相同的目的:
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中使用所有内核:
library(foreach)
library(doSNOW)
c1 <- makeCluster(8, type = "SOCK")
registerDoSNOW(c1)
但这没有帮助。我看了所有有关慢循环的博客和其他文章,但是我的代码只是一行,所以在其他建议中我看不到任何能使速度更快的方法。
任何帮助使此循环在不到一分钟的时间内运行的方法,将非常感激。
答案 0 :(得分:0)
这看起来像是创建联接的原因,而dplyr
包正是您想要的。
我没有您的数据,但是根据您的代码,我整理了一些简单的虚假数据,看起来像您的结构一样。
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
答案 1 :(得分:0)
循环可能不是执行此操作的最佳方法。一种替代方法是将cat.growth数据(44 x 8)整形为具有县,类别和增长因子(即352 x 3)变量的data.frame,然后在此数据帧和原始数据帧上使用“合并”。
为了说明我的意思(根据我对您数据的理解):
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)
答案 2 :(得分:0)
正如其他人指出的那样,您不应使用循环。但是您的问题似乎是“为什么这个循环要花这么长时间?”
答案是,您似乎遍历了parcel.data.1$county
的所有136万个元素和parcel.data.1$classification
的所有136万个元素。这意味着您的循环正在评估ifelse()
1360000^2
次,而不是352次。
如果要使用循环,请循环遍历每列的 unique 元素,这些元素由行名和列名cat.growth
给出。
for (x in rownames(cat.growth)) { # loop over counties
for (y in colnames(cat.growth)) { # loop over classifications
...
}
}
此循环等效于您的原始脚本,其中包含352行代码,因此它的运行时间应该大致相同,约为16秒。
请注意,如果您还不知道这两个向量的唯一元素,则可以使用unique()
来找到它们。