2013-08-16 99 views
5

我試圖尋找多年運行在一個數據幀(最好使用plyr)查找範圍中的數字

的運行,我想從這個獲得:

require(plyr) 

dat<-data.frame(
    name=c(rep("A", 11), rep("B", 11)), 
    year=c(2000:2010, 2000:2005, 2007:2011) 
) 

爲此:

out<-data.frame(
    name=c("A", "B", "B"), 
    range=c("2000-2010", "2000-2005", "2007-2011")) 

這是很容易識別每個組是否具有多年連續運行:

ddply(dat, .(name), summarise, 
     continuous=(max(year)-min(year))+1==length(year)) 

我該如何將組「B」分解爲兩個範圍?

任何想法或策略將非常感激。

感謝

回答

7

無論您使用的功能從「plyr」或基礎R,則需要先建立一些羣體。一種方法來檢測自從你連續數年後的組中的變化是尋找diff不等於1的位置。diff創建一個長度小於輸入向量的向量,因此我們將用「1」初始化該向量並採取結果的cumsum

把的解釋,即一口付諸實踐,你可以嘗試這樣的事:

dat$id2 <- cumsum(c(1, diff(dat$year) != 1)) 

在這裏,您可以使用aggregate或你最喜歡的分組功能,讓你正在尋找的輸出。

aggregate(year ~ name + id2, dat, function(x) paste(min(x), max(x), sep = "-")) 
# name id2  year 
# 1 A 1 2000-2010 
# 2 B 2 2000-2005 
# 3 B 3 2007-2011 

要與aggregate使用range,你需要如下改變sepcollapse,:

aggregate(year ~ name + id2, dat, function(x) paste(range(x), collapse = "-")) 
+1

+1非常好的解決方案。 –

+0

真棒 - 我從來沒有想到這一點。對於plyr,我可以用ddply(dat,。(name,id2),彙總,粘貼(min(year),「:」,max(year),sep =「」))來完成它。 –

+0

@EdG或'ddply(dat,「id2」,summary,Range = paste(range(year),collapse =「 - 」))' –

2

Tooting我自己的號角,cgwtools::seqle可以用來識別分裂。碾過names元素的循環或*apply,併爲每一種情況下,

foo <- seqle(dat$year, incr=1) 

然後length(foo$lengths)會給你組的數量,和歲月的範圍很容易從foo$values重建。

yeargroups <- sapply(length(foo$lengths), function(x) c(foo$values[x],(foo$values[x]+foo$lengths[x]-1))) 

只是提出這種情況下,有人有不同的參數或所需的細分類似的情況。

+0

+1。我會提到它,但我想我會給你一個機會炫耀你的包:) – A5C1D2H2I1M1N2O1R2T1