Как выбрать несколько строк на основе другого столбца? - PullRequest
0 голосов
/ 19 мая 2019

У меня есть фрейм данных с множеством столбцов и строк с множеством идентификаторов, следующие данные показывают только 2 идентификатора.

id  treatment  
1   A          
1   B          
1   C          
1   D          
1   E          
2   A          
2   B         
2   C  

Я хочу получить подгруппу идентификатора с пятью обработками (A, B, С, D, Е).Таким образом, выходная таблица будет выглядеть так:

id  treatment
1   A          
1   B        
1   C           
1   D           
1   E   

Большое спасибо.

Ответы [ 6 ]

1 голос
/ 19 мая 2019

Чтобы вернуть подмножество групп идентификаторов, которые содержат все обработки, выполните что-то вроде следующего:

install.packages("dplyr")
library(dplyr)

treatments <- c("A", "B", "C", "D", "E")

df %>% group_by(id) %>% filter(all(treatments %in% treatment))

#### OUTPUT ####

# A tibble: 5 x 2
# Groups:   id [1]
     id treatment
  <int> <fct>    
1     1 A        
2     1 B        
3     1 C        
4     1 D        
5     1 E        

Основное преимущество здесь состоит в том, что он правильно обрабатывает повторяющиеся условия.То есть, в случае, если у вас есть идентичное условие в группе идентификаторов, например:

# A tibble: 11 x 2
      id treatment
   <dbl> <chr>    
 1     1 A        
 2     1 A        
 3     1 B        
 4     1 C        
 5     1 D        
 6     1 E        
 7     2 A        
 8     2 A        
 9     2 B        
10     2 B        
11     2 C        

Приведенный выше код вернет все наблюдения любых групп, содержащих каждое условие:

# A tibble: 6 x 2
# Groups:   id [1]
     id treatment
  <dbl> <chr>    
1     1 A        
2     1 A        
3     1 B        
4     1 C        
5     1 D        
6     1 E        
0 голосов
/ 19 мая 2019

Вот способ для базы R с использованием subset и ave (заимствование данных @ steveb):

treatments <- LETTERS[1:5]
subset(treatment.df, as.logical(ave(treatment, id, FUN = function(x) all(treatments %in% x))))
#   id treatment
# 1  1         A
# 2  1         B
# 3  1         C
# 4  1         D
# 5  1         E
0 голосов
/ 19 мая 2019

Я подумал, что было бы интересно дать решение на основе R,

DF = data.frame(id = c(rep(1,5),rep(2,3)), treatment = c('A','C','B','D','E','A','B','C'))

Обратите внимание, что я немного изменил порядок в treatment, чтобы учесть его возможность.

do.call(rbind,
  lapply(split(DF,DF$id),
    function(X){
      if(identical(sort(unique(X$treatment)),c('A','B','C','D','E'))) X
      else NULL}))

Я допускаю возможность того, что id может иметь кратные одинаковые обработки, так как неясно, как выглядит остальная часть data.frame и что обработки для группы id могут быть не отсортированы.

0 голосов
/ 19 мая 2019

Также возможна dplyr:

df %>%
 group_by(id) %>%
 filter(grepl("A,B,C,D,E", paste(treatment, collapse = ","), fixed = TRUE))

     id treatment
  <int> <chr>    
1     1 A        
2     1 B        
3     1 C        
4     1 D        
5     1 E 

Здесь также учитывается порядок, то есть отфильтровываются случаи, когда лечение не идет A,B,C,D,E.

Еслипорядок не важен, тогда вы можете сначала расположить столбец «обработки»:

df %>%
 group_by(id) %>%
 arrange(treatment, .by_group = TRUE) %>%
 filter(grepl("A,B,C,D,E", paste(treatment, collapse = ","), fixed = TRUE))

Учитывая сценарий, показанный @gersht, его можно изменить на:

df %>%
 group_by(id) %>%
 filter(grepl("A,B,C,D,E", paste(unique(treatment), collapse = ","), fixed = TRUE))

Или:

df %>%
 group_by(id) %>%
 arrange(treatment, .by_group = TRUE) %>%
 filter(grepl("A,B,C,D,E", paste(unique(treatment), collapse = ","), fixed = TRUE))
0 голосов
/ 19 мая 2019

Один из следующих вариантов: dplyr.

РЕДАКТИРОВАТЬ

Это более краткое решение, и исходное решение приведено ниже.Это более короткое решение также удаляет повторяющиеся строки.num.treatments жестко запрограммирован на 5, но может быть установлен любым способом.

library(dplyr)

# load your data
treatment.df <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L), treatment = c("A", "B", "C", "D", "E", "A", "B", "C")), class = "data.frame", row.names = c(NA, -8L))
num.treatments <- 5
unique(treatment.df[c("id", "treatment")]) %>%
  group_by(id) %>%
  filter(n() == num.treatments)

Исходное решение

library(dplyr)

# load your data
treatment.df <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L), treatment = c("A", "B", "C", "D", "E", "A", "B", "C")), class = "data.frame", row.names = c(NA, -8L))
treatment.df
##   id treatment
## 1  1         A
## 2  1         B
## 3  1         C
## 4  1         D
## 5  1         E
## 6  2         A
## 7  2         B
## 8  2         C

## Get IDs with a complete set of treatments
ids.with.all.treatments <-
  treatment.df %>%
  group_by(id, treatment) %>%
  summarise() %>%          # Get unique set if id/treatment pairs in cases of duplicates.
  summarise(cnt = n()) %>% # Summarise by 'id' to the count per id.
  filter(cnt == 5)         # Get items with the expected number of treatments


treatment.df %>%
  filter(id %in% ids.with.all.treatments$id)
##   id treatment
## 1  1         A
## 2  1         B
## 3  1         C
## 4  1         D
## 5  1         E
0 голосов
/ 19 мая 2019

Вот супер лаконичный способ сделать это:

 head(my.data)
  id treatment
1  1         A
2  1         B
3  1         C
4  1         D
5  1         E
6  2         A

group_by(my.data, id) %>% filter(n_distinct(treatment) == 5)
# A tibble: 5 x 2
# Groups:   id [1]
     id treatment     
  <int> <chr>     
1     1 A            
2     1 B            
3     1 C            
4     1 D            
5     1 E   

Объяснение

Внутренне, n_distinct(treatment) подсчитывает экземпляры уникальных значений в каждой категории id, так как вы сгруппированы по этому столбцу. Затем фильтр сохраняет id с, которые произошли 5 раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...