2017-08-22 33 views
1

我是一个数年的潜伏者,但我终于找到了一些我无法用旧帖子找出的东西。我有包含上百个国家,多年的数据帧,并用二进制指示的事件变量:按小组计算多个连续事件w /起始年份

library('dplyr') 
library('data.table') 

country<-c("albania","albania","albania","albania","albania","albania","albania","albania","thailand","thailand","thailand","thailand","thailand","thailand","thailand","thailand") 
year<-c(1960,1961,1962,1963,1964,1965,1966,1967,1972,1973,1974,1975,1976,1977,1978,1979) 
event<-c(0,1,1,0,0,1,1,1,1,1,0,0,1,0,0,0) 
input<-data.frame(country=country, year=year, event=event) 

input  

    country year event 
1 albania 1960  0 
2 albania 1961  1 
3 albania 1962  1 
4 albania 1963  0 
5 albania 1964  0 
6 albania 1965  1 
7 albania 1966  1 
8 albania 1967  1 
9 thailand 1972  1 
10 thailand 1973  1 
11 thailand 1974  0 
12 thailand 1975  0 
13 thailand 1976  1 
14 thailand 1977  0 
15 thailand 1978  0 
16 thailand 1979  0 

我想创建显示多个连续的事件,每个国家有自己的时间新的数据帧和开始一年。例如:

output 

    country start duration 
1 albania 1961  2 
2 albania 1965  3 
3 thailand 1972  2 
4 thailand 1976  1 

我读过了,我所相信的是,大多数关于使用rle()rleid()dplyrdata.table按组计算连续的事件相关的帖子,但我不能让他们到我想成为的地方。

正在关注this example,我无法获得一个国家多个事件长度的新数据框;不只是最大值,最小值等,并且忽略了我需要抓住事件的起始年份。试图建立这个代码来达到我想要的状态给我留下了很多错误。 “基本规范”为dplyr例子似乎是一些出发点:

output <- input %>% 
group_by(country) %>% 
do({ 
tmp <- with(rle(.$event == 1), lengths[values]) 
data.frame(country= .$country, Max = if (length(tmp) == 0) 0 else max(tmp)) 
}) %>% 
slice(1L) 

这显然拉动最大,我挣扎着试图改变它拉每个事件。

Following the data.table/rleid模型创建了一个新突变的变量,用于统计连续“事件”的持续时间,但我无法提取一个国家内多个事件的“结束”年份。也许一些滞后差异函数使用突变变量,然后提取负值的所有行?一旦结束事件的行被标记,起始年份将仅是当前年份 - 长度。这种方法的基本代码是:

sum0 <- function(x) { x[x == 1] = sequence(with(rle(x), lengths[values == 1])); x } 
setDT(input)[, duration := sum0(event), by = country] 

input 

    country year event duration 
1: albania 1960  0  0 
2: albania 1961  1  1 
3: albania 1962  1  2 
4: albania 1963  0  0 
5: albania 1964  0  0 
6: albania 1965  1  1 
7: albania 1966  1  2 
8: albania 1967  1  3 
9: thailand 1972  1  1 
10: thailand 1973  1  2 
11: thailand 1974  0  0 
12: thailand 1975  0  0 
13: thailand 1976  1  1 
14: thailand 1977  0  0 
15: thailand 1978  0  0 
16: thailand 1979  0  0 

有另一个7-10的帖子我看了,通过但没有链接,因为它们在本质上是两个我引用相似。我想先感谢任何有任何建议的人。我希望我遵循所有提出问题的协议;我试图小心并遵守规则。感谢你们所做的所有伟大的工作!你已经通过了5-6年的R和JAGS学习。

回答

3

这里是我会做什么(离开dplyr出来的):

setDT(input) 

input[, 
    if (first(event) == 1) .(year = first(year), N = .N) 
, by=.(country, g = rleid(country, event))][, !"g"] 

    country year N 
1: albania 1961 2 
2: albania 1965 3 
3: thailand 1972 2 
4: thailand 1976 1 

效率不高,但希望很容易效仿。

+0

比我的解决方案更好。 – mt1022

+0

@ mt1022我不同意。我认为,你的效率和惯用性更高。 – Frank

+0

看起来不错,我不得不走出一段时间。我会检查什么时候回来。谢谢你的帮助;我刚开始学习data.table,所以对我来说有些陌生。 –

2

这是你想要的东西:

library(data.table) 

setDT(input) 
input[, .(event = event[1], start = year[1], duration = .N), 
     by = .(country, rleidv(event))][event == 1][ 
      , c('event', 'rleidv') := NULL][] 

#  country start duration 
# 1: albania 1961  2 
# 2: albania 1965  3 
# 3: thailand 1972  2 
# 4: thailand 1976  1 

正如评论指出弗兰克,这个解决方案是由data.table在计算,这使得它更高效的优化。 if(cond) ...中的j表达式将不会被优化。

+0

正如我上面所说:看起来是正确的,我必须走出一段时间。我会检查什么时候回来。谢谢你的帮助;我刚开始学习data.table,所以对我来说有些陌生。 –