我想从下面的数据框创建一个平衡的面板数据:
id program_year value
1 2007 1
1 2008 1
1 2009 1
1 2010 1
1 2011 1
1 2012 1
1 2013 0
2 2007 0
2 2008 1
2 2009 1
2 2010 1
2 2011 1
2 2012 1
2 2013 1
3 2007 1
3 2008 0
3 2009 1
3 2010 1
3 2011 1
3 2012 1
3 2013 1
对于每个id
,我要选择5行,这些行具有连续的value == 1
在program_year
列
预期的输出应该如下所示:
id program_year value
1 2007 1
1 2008 1
1 2009 1
1 2010 1
1 2011 1
2 2008 1
2 2009 1
2 2010 1
2 2011 1
2 2012 1
3 2009 1
3 2010 1
3 2011 1
3 2012 1
3 2013 1
我已经探索了lead()
和lag()
,但没有任何成功。获得所需输出后的下一步是索引年份,使数据帧成为一个平衡的面板。
不确定这是否是您需要的:
Data <- "id program_year value
1 2007 1
1 2008 1
1 2009 1
1 2010 1
1 2011 1
1 2012 1
1 2013 0
2 2007 0
2 2008 1
2 2009 1
2 2010 1
2 2011 1
2 2012 1
2 2013 1
3 2007 1
3 2008 0
3 2009 1
3 2010 1
3 2011 1
3 2012 1
3 2013 1"
DF <- read.table(text = Data, header = TRUE)
library(dplyr)
DF %>%
arrange(id, program_year) %>%
group_by(id) %>%
filter((program_year - lag(program_year)) >= 1) %>%
mutate(consecutive = program_year - row_number()) %>%
group_by(id, consecutive) %>%
filter(n() >= 5) %>%
slice_head(n = 5) %>%
ungroup() %>%
filter(value == 1) %>%
select(id, program_year, value)
返回以下内容:
# A tibble: 14 × 3
id program_year value
<int> <int> <int>
1 1 2008 1
2 1 2009 1
3 1 2010 1
4 1 2011 1
5 1 2012 1
6 2 2008 1
7 2 2009 1
8 2 2010 1
9 2 2011 1
10 2 2012 1
11 3 2009 1
12 3 2010 1
13 3 2011 1
14 3 2012 1
修改答案以满足您的条件where value == 1
下面是使用dplyr::consecutive_id()
和每个操作分组的解决方案。请确保您使用的是最新版本的dplyr。
library(dplyr) # >= v1.1.0
dat %>%
mutate(c_id = consecutive_id(value), .by = id) %>%
filter(value == 1, n() >= 5, .by = c(id, c_id)) %>%
filter(row_number() <= 5, .by = id) %>%
select(!c_id)
id program_year value
1 1 2007 1
2 1 2008 1
3 1 2009 1
4 1 2010 1
5 1 2011 1
6 2 2008 1
7 2 2009 1
8 2 2010 1
9 2 2011 1
10 2 2012 1
11 3 2009 1
12 3 2010 1
13 3 2011 1
14 3 2012 1
15 3 2013 1
这里的技巧是创建两个虚拟列:首先是行号列,然后是按列分组的虚拟列。最后,从结果中取消选择虚拟列。
df %祝辞% group_by (id) %祝辞%安排(program_year) %祝辞%过滤器(价值! = 0)%祝辞%变异(row_num = row_number (), dummygroup = program_year-row_num) %祝辞% group_by (id、dummygroup) %祝辞%安排(id、desc (program_year)) %祝辞%过滤器(n()在= 5,row_number () & lt; = 5)
在by
中,对于每个ID,我们可以首先为非零值创建subset
,为连续值集创建u
组,为table
中产生which.max
个数的组创建subset
x
组。接下来我们head
类列表"by"
对象为min
的最大观测次数,最后rbind
。
by(dat, dat$id, (x) {
x <- subset(x, x$value == 1)
u <- cumsum(c(1, diff(x$program_year)) != 1) + 1
tbl <- table(u)
subset(x, u == which.max(tbl))
}) |> {(.) lapply(., (x) {
m <- min(sapply(., nrow))
transform(head(x, m), period=seq_len(m))
})}() |> ## or `tail` instead of `head`
do.call(what='rbind')
# id program_year value period
# 1.1 1 2007 1 1
# 1.2 1 2008 1 2
# 1.3 1 2009 1 3
# 1.4 1 2010 1 4
# 1.5 1 2011 1 5
# 2.9 2 2008 1 1
# 2.10 2 2009 1 2
# 2.11 2 2010 1 3
# 2.12 2 2011 1 4
# 2.13 2 2012 1 5
# 3.17 3 2009 1 1
# 3.18 3 2010 1 2
# 3.19 3 2011 1 3
# 3.20 3 2012 1 4
# 3.21 3 2013 1 5
给出给定id的连续观测的最大可能子集,尽管在OP中要求不匹配年,但增加了一个新的周期变量。
数据:
dat <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), program_year = c(2007L,
2008L, 2009L, 2010L, 2011L, 2012L, 2013L, 2007L, 2008L, 2009L,
2010L, 2011L, 2012L, 2013L, 2007L, 2008L, 2009L, 2010L, 2011L,
2012L, 2013L), value = c(1L, 1L, 1L, 1L, 1L, 1L, 0L, 0L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 0L, 1L, 1L, 1L, 1L, 1L)), class = "data.frame", row.names = c(NA,
-21L))