如果整个组都满足条件,如何仅保留data.frame的那些行

时间:2018-10-16 19:05:02

标签: r date dataframe

我对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中做到这一点?

3 个答案:

答案 0 :(得分:1)

如果我正确理解了您的要求,这是使用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

答案 1 :(得分:0)

这是使用dplyr执行此操作的方法。这会寻找所有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 :(得分:0)

出于完整性考虑,以下是一些解决方案:

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组中,仅返回df的那些子集,其中有多个不同的Type


这也可以写成:

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)