R中的组数据用于连续行

时间:2015-09-11 15:53:25

标签: r

如果在R中没有快速1-3衬里,我绝对会使用linux sort和使用groupby的短python程序,所以不要向后弯腰试图得到一些疯狂的工作。这是输入数据框:

df_in <- data.frame(
  ID = c(1,1,1,1,1,2,2,2,2,2),
  weight = c(150,150,151,150,150,170,170,170,171,171),
  start_day = c(1,4,7,10,11,5,10,15,20,25),
  end_day = c(4,7,10,11,30,10,15,20,25,30)
)
   ID weight start_day end_day
1   1    150         1       4
2   1    150         4       7
3   1    151         7      10
4   1    150        10      11
5   1    150        11      30
6   2    170         5      10
7   2    170        10      15
8   2    170        15      20
9   2    171        20      25
10  2    171        25      30

我想通过IDweight进行一些基本的聚合,但仅限于该组在df_in的连续行中。具体来说,所需的输出是

df_desired_out <- data.frame(
  ID = c(1,1,1,2,2),
  weight = c(150,151,150,170,171),
  min_day = c(1,7,10,5,20),
  max_day = c(7,10,30,20,30)
)
  ID weight min_day max_day
1  1    150       1       7
2  1    151       7      10
3  1    150      10      30
4  2    170       5      20
5  2    171      20      30

question似乎与我想要的非常接近,但出于某种原因我很难适应它。

3 个答案:

答案 0 :(得分:5)

dplyr 中,我会通过为连续行创建另一个分组变量来完成此操作。这就是代码cumsum(c(1, diff(weight) != 0)在下面的代码块中所做的事情。这方面的一个例子也是here

可以在group_by内完成群组创建,然后您可以相应地按群组进行任何摘要。

library(dplyr)

df_in %>%
    group_by(ID, group_weight = cumsum(c(1, diff(weight) != 0)), weight) %>%
    summarise(start_day = min(start_day), end_day = max(end_day))

Source: local data frame [5 x 5]
Groups: ID, group_weight [?]

     ID group_weight weight start_day end_day
  (dbl)        (dbl)  (dbl)     (dbl)   (dbl)
1     1            1    150         1       7
2     1            2    151         7      10
3     1            3    150        10      30
4     2            4    170         5      20
5     2            5    171        20      30

这种方法确实为您留下了数据集中的额外分组变量,如果需要,可以在取消分组后使用select(-group_weight)删除。

答案 1 :(得分:1)

首先,我们结合IDweight。快捷方法是使用粘贴:

df_in$id_weight <- paste(df_in$id, df_in$weight, sep='_')
df_in
   ID weight start_day end_day id_weight
1   1    150         1       4     1_150
2   1    150         4       7     1_150
3   1    151         7      10     1_151
4   1    150        10      11     1_150
5   1    150        11      30     1_150
6   2    170         5      10     2_170
7   2    170        10      15     2_170
8   2    170        15      20     2_170
9   2    171        20      25     2_171
10  2    171        25      30     2_171

更安全的方法是使用interactiongroup_indicesCombine values in 4 columns to a single unique value

我们可以使用rle连续分组。

rlel <- rle(df_in$id_weight)$lengths
df_in$group <- unlist(lapply(1:length(rlel), function(i) rep(i, rlel[i])))
df_in
   ID weight start_day end_day id_weight group
1   1    150         1       4     1_150     1
2   1    150         4       7     1_150     1
3   1    151         7      10     1_151     2
4   1    150        10      11     1_150     3
5   1    150        11      30     1_150     3
6   2    170         5      10     2_170     4
7   2    170        10      15     2_170     4
8   2    170        15      20     2_170     4
9   2    171        20      25     2_171     5
10  2    171        25      30     2_171     5

现在有了方便的组号,我们可以按组进行汇总。

df_in %>% 
  group_by(group) %>% 
  summarize(id_weight = id_weight[1], 
            start_day = min(start_day), 
            end_day = max(end_day))
# A tibble: 5 x 4
  group id_weight start_day end_day
  <int> <chr>         <dbl>   <dbl>
1     1 1_150             1       7
2     2 1_151             7      10
3     3 1_150            10      30
4     4 2_170             5      20
5     5 2_171            20      30

答案 2 :(得分:0)

with(df_in, {
  aggregate(day, list('ID'=ID, 'weight'=weight), 
            function(x) c('min_day' = min(x), 'max_day' = max(x)))
})

产地:

  ID weight x.min_day x.max_day
1  1    150         1         5
2  1    151         3         3
3  2    170         1         3
4  2    171         4         5