我是一个几年的潜伏者,但我终于找到了一些我只能用旧帖子弄清楚的东西。我有一个数据框,包含数百个国家/地区,年份和带有二进制指示符的事件变量:
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
我已经阅读过,我认为是大多数关于使用dplyr
和data.table
rle()
和rleid()
按小组计算连续事件的相关帖子,但我无法将它们带到我想要的地方。
关注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。
答案 0 :(得分: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
效率不高,但希望能够轻松实现。
答案 1 :(得分: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
正如Frank在评论中指出的那样,此解决方案在计算中由data.table
优化,这使其更有效。 <{1}}表达式中的if(cond) ...
将不会被优化。