我有一个由以下内容组成的数据框:
df[1] <- c(red, white, blue, Flag, red, yellow, black, Flag, Flag, white, red, Flag)
我希望旁边有一个列表,其中包含不列出双打的标志数字,除非它们之间报告颜色。 所以它应该是:
df[2] <- c(1,1,1,1,2,2,2,2,2,3,3,3)
我有一个代码在for循环中执行此操作:
#list of unique Flags
numrows<-nrow(df[1])
df[2]<-rep(1,numrows)
counter<-1
for (i in 1:12){
if (df[i,1]=="Flag" & df[i+1,1]!="Flag"){
df[i,2]<-counter
counter<-counter+1
}else{
df[i,2]<-counter
}
}
df[numrows,2]<-counter
问题是我的完整数据集有650.000行,需要8个多小时。有没有办法在R中没有for循环的情况下得到这个特定的结果?
答案 0 :(得分:1)
以下是使用cumsum()
和data.table()
的稍微复杂的解决方案 - 利用.SD
对象仅标记具有颜色跟随的“标志”。我确信通过一些思考可以使它更加简洁。
650k行的6.24秒
require(data.table)
# function to return leading 1 and trailing 0s for each instance of flag
# no 1 returned for single instance (duplicate)
get_s<-function(x){
ifelse(x==1,
y<-c(0),
y<-c(1,rep(0,x-1))
)
return(y)
}
system.time({
df<-data.frame(V1=sample(c("red", "white", "blue", "Flag", "yellow", "black"),650000,T)) #650k rows
df$V2<-cumsum(ifelse(df$V1=="Flag",1,0)) #index each "Flag"
df$V2<-cumsum(data.table(df,key="V2")[,list(get_s(nrow(.SD))),by="V2"][,V1]) #return 1 for Flags with following color
})
#user system elapsed
#6.16 0.06 6.24