【问题标题】:How to keep only those rows of a data.frame if whole group fulfills condition如果整个组满足条件,如何仅保留 data.frame 的那些行
【发布时间】:2019-03-21 09:28:40
【问题描述】:

我对 R 相当陌生,我有一个问题是如何根据 ID 和日期只保留某些值。我有一个(相当大的)数据集,如下例所示:

ID Type Date
1  OUT 2016-06-18
1  OUT 2016-06-18
1  OUT 2016-06-18
1  IN  2016-06-25
1  OUT 2016-06-25
2  IN  2016-07-03
2  OUT 2016-07-03

我现在的问题是如何找到仅包含一种类型(IN 或 OUT)的日期并将其从数据中删除。但是,如果类型是一对(IN 和 OUT)并且 ID 值相同,我想保留日期。

有没有办法在 R 中做到这一点?

【问题讨论】:

标签: r date dataframe


【解决方案1】:

这是使用dplyr 执行此操作的一种方法。这将查找所有具有至少每个 In 和 Out 之一的 ID + Date 组合。

has_both <- df1 %>%
  count(ID, Date, Type) %>%  # How many rows with each combo ID / Date / Type
  count(ID, Date) %>% # How many rows appear for each ID / Date
  filter(nn == 2) %>% # Only keep where 2 types (IN and OUT, presumably)
  left_join(df1)  %>% # Bring back matching original data

输出

has_both
# A tibble: 4 x 4
     ID Date          nn Type 
  <int> <chr>      <int> <chr>
1     1 2016-06-25     2 IN   
2     1 2016-06-25     2 OUT  
3     2 2016-07-03     2 IN   
4     2 2016-07-03     2 OUT 

【讨论】:

    【解决方案2】:

    如果我正确理解了您的要求,这是使用dplyr 包的简单方法-

    df %>%
      group_by(ID, Date) %>%
      filter(n_distinct(Type) > 1)
    
    # A tibble: 4 x 3
    # Groups:   ID, Date [2]
         ID Type  Date      
      <int> <chr> <chr>     
    1     1 IN    2016-06-25
    2     1 OUT   2016-06-25
    3     2 IN    2016-07-03
    4     2 OUT   2016-07-03
    

    从基础 R 中使用 ave() 的另一种方式 -

    df[with(df, ave(Type, ID, Date, FUN = function(x) length(unique(x)))) == 2, ]
    
      ID Type       Date
    4  1   IN 2016-06-25
    5  1  OUT 2016-06-25
    6  2   IN 2016-07-03
    7  2  OUT 2016-07-03
    

    【讨论】:

      【解决方案3】:

      为了完整起见,这里也有一些的解决方案:

      library(data.table)
      
      setDT(df)[, if (uniqueN(Type) > 1) .SD, by = .(ID, Date)]
      
         ID       Date Type
      1:  1 2016-06-25   IN
      2:  1 2016-06-25  OUT
      3:  2 2016-07-03   IN
      4:  2 2016-07-03  OUT
      

      在每个IDDate 组内,仅返回有多个不同Typedf 子集。


      这也可以写成:

      setDT(df)[, .SD[uniqueN(Type) > 1], by = .(ID, Date)]
      

      还有一个变体可以通过加入找到满足要求的IDDate 组合和子集df

      setDT(df)[df[, uniqueN(Type), by = .(ID, Date)][V1 > 1], on = .(ID, Date), .SD]
      
         ID Type       Date
      1:  1   IN 2016-06-25
      2:  1  OUT 2016-06-25
      3:  2   IN 2016-07-03
      4:  2  OUT 2016-07-03
      

      数据

      df <-readr::read_delim(
      "ID Type Date
      1  OUT 2016-06-18
      1  OUT 2016-06-18
      1  OUT 2016-06-18
      1  IN  2016-06-25
      1  OUT 2016-06-25
      2  IN  2016-07-03
      2  OUT 2016-07-03", 
      delim = " ", trim_ws = TRUE)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-14
        • 1970-01-01
        • 2021-10-30
        • 2018-01-09
        • 1970-01-01
        • 1970-01-01
        • 2020-05-16
        • 2019-12-10
        相关资源
        最近更新 更多