根据数据框

时间:2018-02-05 12:13:41

标签: r dataframe dplyr

我有一个包含三列的数据框,其中第一列是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))

应该输出与输入相同的输出。

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)

dplyr回答

查看多年(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)

类似的解决方案,但使用completerleid包中的tidyrdata.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