Как сохранить значения, встречающиеся только в одной группе?

#r #data-manipulation

#r #манипулирование данными

Вопрос:

Я работаю над фреймом данных, который нравится:

 groups .  values
a .        1
a .        1
a          2
b .        2
b .        3
b .        3
c .        4
c .        5
c .        6
d .        6
d .        7
d .        2
  

Проблема в том, чтобы превратить это во что-то вроде:

 groups .  values
a .        1
a .        1
b .        3
b .        3
c .        4
c .        5
d .        7
  

Я хочу сохранить строки, значения которых встречаются только в ОДНОЙ группе. Например, значение 2 удаляется, потому что оно встречается в трех разных группах, но значение 1 сохраняется, хотя оно встречается дважды ТОЛЬКО в ОДНОЙ группе.

Есть ли какие-либо функции из пакета dplyr, которые могут справиться с этой проблемой? или я должен написать свою собственную функцию?

Комментарии:

1. Что у вас есть на данный момент?

2. Я пробовал что-то вроде «DATAFRAME %>% group_by (группы) %>% distinct (значения)», но он сохраняет только уникальные значения в каждой группе.

Ответ №1:

Как вы просили dplyr решение:

 df %>% group_by(values) %>% filter(n_distinct(groups) == 1)
# # A tibble: 7 x 2
# # Groups:   values [5]
# groups values
# <chr>   <int>
#1 a           1
#2 a           1
#3 b           3
#4 b           3
#5 c           4
#6 c           5
#7 d           7
  

с

 df <- structure(list(groups = c("a", "a", "a", "b", "b", "b", "c", "c", "c", "d", "d", "d"),
                     values = c(1L, 1L, 2L, 2L, 3L, 3L, 4L, 5L, 6L, 6L, 7L, 2L)),
                row.names = c(NA, -12L), class = "data.frame")
  

Ответ №2:

Сгруппируйте по values и посмотрите, содержит ли столбец groups только один элемент. Это можно сделать с помощью ave .

 i <- as.logical(with(df1, ave(as.numeric(groups), values, FUN = function(x) length(unique(x)) == 1)))
df1[i, ]
#   groups values
#1       a      1
#2       a      1
#5       b      3
#6       b      3
#7       c      4
#8       c      5
#11      d      7
  

Данные в dput формате.

 df1 <-
structure(list(groups = structure(c(1L, 1L, 1L, 2L, 
2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L), .Label = c("a", "b", 
"c", "d"), class = "factor"), values = c(1L, 1L, 2L, 
2L, 3L, 3L, 4L, 5L, 6L, 6L, 7L, 2L)), 
class = "data.frame", row.names = c(NA, -12L))
  

Ответ №3:

 x[x$values %in% names(which(colSums(table(x)>0)==1)),]
  

где

 x = structure(list(groups = c("a", "a", "a", "b", "b", "b", "c", 
  "c", "c", "d", "d", "d"), values = c(1L, 1L, 2L, 2L, 3L, 3L, 
    4L, 5L, 6L, 6L, 7L, 2L)), row.names = c(NA, -12L), class = "data.frame")
  

или data.table решение:

 setDT(x)[, .SD[uniqueN(groups)==1], values]
  

Ответ №4:

Использование sqldf пакета для вашего исходного фрейма данных df :

 library(sqldf)
result <- sqldf("SELECT * FROM df
                 WHERE `values` IN (
                     SELECT `values` from (
                         SELECT `values`, groups, count(*) as num from df
                         GROUP BY `values`, groups) t
                      GROUP BY `values` 
                      HAVING COUNT(1) = 1
                 )")