根据不同的行条件删除组行

时间:2016-01-04 21:10:44

标签: r data.table dplyr zoo

这就是我的数据框架的样子。

dt <- read.table(text='

                         Name      ActivityType   GrpID                 
                         John       Sale           1            
                         John       Sale           2              
                         John       Webinar        3           
                         Kyle       Email          1       
                         Kyle       Seminar        2            
                         Kyle       Sale           3          
                         Kyle       Webinar        4
                         Kyle       Sale           5        
                         Tom        Email          1             
                         Tom        Video          2            
                         Tom        Seminar        3           
                                             ', header=T, row.names = NULL)

我想做三件事。

  1. 首先删除组&#39; s(名称是组)的行首先是ActivityType&#34; Sale&#34;。这将删除Name = John
  2. 的行
  3. 删除没有ActivityType = Sale的行。这将删除Name = Tom
  4. 的行
  5. 返回第一个ActivityType不在的剩余组&#34; Sale&#34;但是有一个ActivityType =&#34; Sale&#34;在稍后的某些行中(如1&amp; 2中​​所述)并且仅显示结果直到ActivityType = Sale的第一个实例。所以它应该显示

                Name      ActivityType   GrpID
                 Kyle       Email          1       
                 Kyle       Seminar        2            
                 Kyle       Sale           3 
    

    它不必是所述的3个步骤。我只需要最终输出。我在考虑在data.table中使用SD功能,但不知道如何添加这些条件。我将非常感谢你的帮助。

3 个答案:

答案 0 :(得分:7)

1 Sunday 2 Monday 3 Tuesday 4 Wednesday 5 Thursday 6 Friday 7 Saturday

data.table

(请注意,第三种情况包含前两种,所以我假设你想要三种不同的输出......否则只能坚持到最后一种情况)

答案 1 :(得分:3)

使用dplyr这将适用于上面的示例

dt %>%
    group_by(Name) %>%
    filter( sum((GrpID == 1 & ActivityType=='Sale')) == 0 ) %>%
    filter( sum(ActivityType=='Sale') > 0 ) %>%
    filter( GrpID <= min(GrpID[ActivityType == 'Sale'])) %>%
    ungroup

#Source: local data frame [3 x 3]
#
#    Name ActivityType GrpID
#  (fctr)       (fctr) (int)
#1   Kyle        Email     1
#2   Kyle      Seminar     2
#3   Kyle         Sale     3

虽然可能有更简洁的方法。

编辑:我添加了输出,ungroup删除了分组。

编辑2:根据MichaelChirico的建议

dt %>%
    group_by(Name) %>%
    filter( !any(ActivityType == 'Sale' & GrpID == 1) )  %>% # 1
    filter(  any(ActivityType == 'Sale') )               %>% # 2
    filter( GrpID <= min(GrpID[ActivityType == 'Sale'])) %>% # 3
    ungroup

上述解决方案使用any代替sum%>%是管道运算符)。这并不是说这不能提高效率。如果有人建议更有效和/或更具可读性的dplyr解决方案,我将很乐意再次更新。

编辑3

以下是基于@MichaelChirico的评论/解决方案的第3项的替代解决方案。这将所有3个条件合并到一个过滤器语句中(不使用上面的渐进过滤)。

dt %>%
    group_by(Name) %>%
    mutate(x = (ActivityType == 'Sale') ) %>%
    filter( !x[1],
            any(x),
            row_number() <= which.max(x))  %>%
    ungroup %>%
    select(-x)

答案 2 :(得分:1)

# For those who prefer to roll their own
result.list <- by(dt, dt$Name, FUN = function(x) {
  f <- match("Sale", x$ActivityType)
  if(!is.na(f) & (f != 1) ) return(head(x, f))
})

result.df <- do.call(rbind, result.list)
相关问题