我是R和Stack Overflow的新手,希望您能够解决我遇到的问题。我写了以下代码:
my = matrix(c(1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,
0,1,2,3,5,6,7,10,11,14,
0,1,2,3,4,6,10),ncol = 2, nrow = 17)
colnames(my) = c("ID", "AGE")
my = as.data.frame(my)
my$new = my$ID
system.time(for (i in 1:length(my$ID)) {
ifelse(my$ID[i]==my$ID[i-1],
ifelse(my$AGE[i]-my$AGE[i-1]==1, my$new[i]<-my$new[i-1],my$new[i]<-my$new[i-1]+0.1),
my$new[i]<-my$ID[i])
})
它查看ID和AGE,如果AGE不等于以前的AGE + 1,则它将ID加0.1,并将其保留在“ new”列中。输出如下:
ID AGE new
1 1 0 1.0
2 1 1 1.0
3 1 2 1.0
4 1 3 1.0
5 1 5 1.1
6 1 6 1.1
7 1 7 1.1
8 1 10 1.2
9 1 11 1.2
10 1 14 1.3
11 2 0 2.0
12 2 1 2.0
13 2 2 2.0
14 2 3 2.0
15 2 4 2.0
16 2 6 2.1
17 2 10 2.2
问题是,对于1000行的数据集,它确实非常快,但是当我在我的实际数据集上进行尝试时,该数据集的行数超过850万,感觉好像永远做不到-我尝试等待几个小时没有成功。
如果您提出提高速度/效率的方法,我将不胜感激。
答案 0 :(得分:1)
处理大型数据集时,您需要尝试向量化计算以提高速度。
以下是使用dplyr
包的示例(由于需要知道lag
的先前值的功能AGE
):
require(dplyr) # for group_by, mutate and %>%
require(microbenchmark) # to compare codes
# Your data
my <- matrix(c(1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,
0,1,2,3,5,6,7,10,11,14,
0,1,2,3,4,6,10), ncol=2, nrow=17)
colnames(my) <- c("ID", "AGE")
my <- as.data.frame(my)
my$new <- my$ID
my2 <- my[rep(1:nrow(my), times=100),] # larger dataset
# Your function
f1 <- function(my) {
for (i in 1:length(my$ID)) {
ifelse(my$ID[i]==my$ID[i-1],
ifelse(my$AGE[i]-my$AGE[i-1]==1, my$new[i] <- my$new[i-1],
my$new[i] <- my$new[i-1]+0.1),
my$new[i] <- my$ID[i])
}
}
# dplyr function
f2 <- function(my) {
my %>% group_by(ID) %>% # Work by ID
mutate(new2=ifelse(is.na(lag(AGE)), # If lag(AGE) is NA, it's the first record for the ID
FALSE, # Thus, no increase of new3
AGE!=lag(AGE)+1), # new3=TRUE if AGE != 1+previous AGE
new3=new+cumsum(new2)/10) # increase the decimal if TRUE for the previous new2
}
对于较小的数据集,for循环更有效,但是对于较大的数据集,改进显而易见:
# Compare codes
microbenchmark(f1(my), f2(my),
f1(my2), f2(my2))
Unit: milliseconds
expr min lq mean median uq max neval cld
f1(my) 1.470699 1.957855 2.750798 2.049954 2.243380 62.34942 100 a
f2(my) 2.741614 3.853356 4.235745 4.147085 4.421738 10.84871 100 a
f1(my2) 156.986927 215.515605 218.806729 222.390968 228.362988 290.19161 100 b
f2(my2) 3.398812 4.377638 5.128953 4.659674 5.161190 28.97461 100 a