2014-07-03 43 views
1

我有這個data.frame稱爲dum累積和在數據幀的中心開始 - R的

dummy <- data.frame(label = "a", x = c(1,1,1,1,0,1,1,1,1,1,1,1,1)) 
    dummy1 <- data.frame(label = "b", x = c(1,1,1,1,1,1,1,1,0,1,1,1,1)) 

    dum <- rbind(dummy,dummy1) 

我所試圖做的是採取的dumx列從0開始的累計總和。總和將按照label列進行分組,該列可以在dplyrplyr中執行。我正在努力的部分是如何從x中的0位置開始累積總和並向外移動。

產生的data.frame應該是這樣的:

>dum 
    label x output 
1  a 1  4 
2  a 1  3 
3  a 1  2 
4  a 1  1 
5  a 0  0 
6  a 1  1 
7  a 1  2 
8  a 1  3 
9  a 1  4 
10  a 1  5 
11  a 1  6 
12  a 1  7 
13  a 1  8 
14  b 1  8 
15  b 1  7 
16  b 1  6 
17  b 1  5 
18  b 1  4 
19  b 1  3 
20  b 1  2 
21  b 1  1 
22  b 0  0 
23  b 1  1 
24  b 1  2 
25  b 1  3 
26  b 1  4 

這將需要在數以百萬計的數據行被重複數千次。

像往常一樣,感謝您的任何和所有幫助

回答

4

這似乎更是快像你只是想找到的距離爲零,而比任何類型的累積總和。如果是這樣的話,那麼

#find zeros for each group 
zeros <- tapply(seq.int(nrow(dum)) * as.numeric(dum$x==0), dum$label, max) 

#calculate distance from zero for each point 
dist <- abs(zeros[dum$label]-seq.int(nrow(dum))) 

這一點讓

cbind(dum, dist) 

# label x dist 
# 1  a 1 4 
# 2  a 1 3 
# 3  a 1 2 
# 4  a 1 1 
# 5  a 0 0 
# 6  a 1 1 
# 7  a 1 2 
# 8  a 1 3 
# 9  a 1 4 
# 10  a 1 5 
# 11  a 1 6 
# 12  a 1 7 
# 13  a 1 8 
# 14  b 1 8 
# 15  b 1 7 
# 16  b 1 6 
# 17  b 1 5 
# 18  b 1 4 
# 19  b 1 3 
# 20  b 1 2 
# 21  b 1 1 
# 22  b 0 0 
# 23  b 1 1 
# 24  b 1 2 
# 25  b 1 3 
# 26  b 1 4 

甚至ave讓你一步到位

dist <- with(dum, ave(x,label,FUN=function(x) abs(seq_along(x)-which.min(x)))) 
cbind(dum, dist) 
+0

效果很好。爲了不浪費我現在刪除的答案,對於一個組中的多個0的這個函數的推廣將是:在2300萬行數據框(在這個例子中是dum $ label)的數據幀上花費了大約5分鐘的時間14000 – user2813055

+0

爲了不浪費我現在刪除的答案, 'do.call(pmin,lapply(which(dum $ x == 0),function(n)abs(n-seq_along(dum $ x))))' – thelatemail

2

你可以做到這一點與by也與plyrdata.table等即每個子集使用功能是

f <- function(d) { 
    x <- d$x 
    i <- match(0, x) 
    v1 <- rev(cumsum(rev(x[1:i]))) 
    v2 <- cumsum(x[(i+1):length(x)]) 
    transform(d, output = c(v1, v2)) 
} 

要調用它在每個子集上,例如與by

res <- by(dum, list(dum$label), f) 
do.call(rbind, res) 

如果你想使用ddply

library(plyr) 
ddply(dum, .(label), f) 

可與data.table

library(data.table) 
dumdt <- as.data.table(dum) 
setkey(dumdt, label) 
dumdt[, f(.SD), by = key(dumdt)] 
+1

' dum [,abs(which.min(x) - seq _along(x)),by = label]'是一個更簡單的'data.table'方法。 – thelatemail

+0

夠公平的,@MrFlick的方式要好得多,如果'x'總是爲0或1,這在OP中沒有明確說明,所以我去了'cumsum'。 – konvas

1

做使用dplyr

library(dplyr) 
dum%>% 
group_by(label)%>% 
mutate(dist=abs(row_number()-which.min(x)))