我有一个包含三列的数据框,其中第一列是ID,第二列表示年份,第三列是与该年度ID相关联的值:
df.in <- data.frame("id"=c(1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
"yr"=c(2005,2006,2007,2009,2010,2011,2012,2013,2006,2007,2008,2009,2010,2011,2012,2013,2015,2016),
"vl"=c(5, 6, 7, 8, 10, 1, 2, 3, 6, 8, 10, 1, 2, 3, 4, 5, 7, 9))
正如您所看到的,给定ID的年份之间存在一些差距。对于ID==1
,有两个连续年份的“组”分别具有3行和5行。对于ID==2
,它分别为8和2。
是否有dplyr
- 方法来生成一个data.frame,它只包含每个ID的行数最多的组,这些行连续相互跟随?换句话说,我想要一个具有5+8
行的数据框:
df.in <- data.frame("id"=c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2),
"yr"=c(2009,2010,2011,2012,2013,2006,2007,2008,2009,2010,2011,2012,2013),
"vl"=c(8, 10, 1, 2, 3, 6, 8, 10, 1, 2, 3, 4, 5))
编辑:再多一个测试用例:
df.in <- data.frame("id"=c(1, 1, 1, 1, 1, 1, 1, 1),
"yr"=c(2005,2006,2007,2008,2009,2010,2011,2012),
"vl"=c(5, 6, 7, 8, 10, 1, 2, 3))
应该输出与输入相同的输出。
答案 0 :(得分:3)
我们在日期组更改时添加一个标志(在按ID分组后),此标志的cumsum为我们提供了一个组ID。
我们按这些组计算行数,并仅保留每个id
值的最大值:
df.in %>%
group_by(id) %>%
mutate(group = cumsum(c(1,yr[1:(length(yr)-1)] < yr[2:length(yr)]-1))) %>%
group_by(id,group) %>%
add_count %>%
group_by(id) %>%
filter(n == max(n)) %>%
select(-n) %>%
ungroup
# # A tibble: 13 x 4
# id yr vl group
# <dbl> <dbl> <dbl> <dbl>
# 1 1 2009 8 2
# 2 1 2010 10 2
# 3 1 2011 1 2
# 4 1 2012 2 2
# 5 1 2013 3 2
# 6 2 2006 6 1
# 7 2 2007 8 1
# 8 2 2008 10 1
# 9 2 2009 1 1
# 10 2 2010 2 1
# 11 2 2011 3 1
# 12 2 2012 4 1
# 13 2 2013 5 1
答案 1 :(得分:1)
查看多年(x
)之间的差距,然后使用cumsum
对其进行分组,然后计算并过滤最大值:
df.in %>%
group_by(id) %>%
mutate(x = ifelse(is.na(lag(yr)), F, lag(yr) != yr - 1)) %>%
mutate(y = cumsum(x)) %>%
group_by(id, y) %>% add_count() %>%
group_by(id) %>% filter(n == max(n)) %>%
select(-x, -y, -n)
答案 2 :(得分:1)
类似的解决方案,但使用complete
和rleid
包中的tidyr
和data.table
函数。
library(dplyr)
library(tidyr)
library(data.table)
df.out <- df.in %>%
group_by(id) %>%
complete(yr = full_seq(yr, period = 1)) %>%
mutate(Group = rleid(is.na(vl))) %>%
group_by(id, Group) %>%
mutate(N = n()) %>%
ungroup() %>%
group_by(id) %>%
filter(N == max(N)) %>%
select(-Group, -N) %>%
ungroup()
df.out
# # A tibble: 13 x 3
# id yr vl
# <dbl> <dbl> <dbl>
# 1 1.00 2009 8.00
# 2 1.00 2010 10.0
# 3 1.00 2011 1.00
# 4 1.00 2012 2.00
# 5 1.00 2013 3.00
# 6 2.00 2006 6.00
# 7 2.00 2007 8.00
# 8 2.00 2008 10.0
# 9 2.00 2009 1.00
# 10 2.00 2010 2.00
# 11 2.00 2011 3.00
# 12 2.00 2012 4.00
# 13 2.00 2013 5.00