Подсчет уникальных символов, присутствующих в группе столбцов - PullRequest
0 голосов
/ 13 ноября 2018

У меня есть следующий набор данных

dat <- data.frame(group = c(1,1,1,1,1), id = c(1,2,3,4,5),
              t1 = c('a','a','b','b','c'),p1 = c(0.98,1,0.5,0.9,1),
              t2 = c('b',NA,'a','c',NA),p2 = c(0.02,NA,0.25,0.10,NA),
              t3 = c(NA,NA,'c',NA,NA),p3 = c(NA,NA,0.25,NA,NA))

Я пытаюсь подсчитать количество уникальных символов, присутствующих в нескольких столбцах (t1, t2, t3) в группе, состоящей из нескольких строк (variable = 'group').Подсчитан ли каждый символ, зависит от того, какие значения p1, p2, p3>> 0,05.

Я пытался ввести этот код для подсчета уникальных символов из всех столбцов

b <- dat %>%
group_by(group) %>%
mutate(total = sum(n_distinct(t1[p1 >= 0.05], na.rm = TRUE),
                            n_distinct(t2[p2 >= 0.05], na.rm = TRUE),
                            n_distinct(t3[p3 >= 0.05], na.rm = TRUE)))

В результате он подсчитывает уникальные символы t1, t2 и t3, а затем суммирует их, что приводит к следующему набору данных, где «total» равно 6

dat <- data.frame(group = c(1,1,1,1,1), id = c(1,2,3,4,5),
              t1 = c('a','a','b','b','c'),p1 = c(0.98,1,0.5,0.9,1),
              t2 = c('b',NA,'a','c',NA),p2 = c(0.02,NA,0.25,0.10,NA),
              t3 = c(NA,NA,'c',NA,NA),p3 = c(NA,NA,0.25,NA,NA),
              total = c(6,6,6,6,6))

Однако, что я собираюсь сделатьподсчитать общее количество уникальных символов во всех столбцах.Другими словами, если «a» было видно в столбце t1, то не считайте «a» в других столбцах (t2, t3).Конечный продукт будет выглядеть следующим набором данных, где «total» равно 3 (обозначая a, b и c как уникальные символы)

dat <- data.frame(group = c(1,1,1,1,1), id = c(1,2,3,4,5),
              t1 = c('a','a','b','b','c'),p1 = c(0.98,1,0.5,0.9,1),
              t2 = c('b',NA,'a','c',NA),p2 = c(0.02,NA,0.25,0.10,NA),
              t3 = c(NA,NA,'c',NA,NA),p3 = c(NA,NA,0.25,NA,NA),
              total = c(3,3,3,3,3))

Спасибо за помощь

Ответы [ 3 ]

0 голосов
/ 13 ноября 2018

Сначала lapply через столбцы p с функцией >= 0.05, а затем выберите строки, в которых результат равен true для всех p столбцов с Reduce('&'. Когда у вас есть строки, вы можете выбрать данные, для которых вы хотите считать уникальные числа, с помощью .SD[rows, paste0('t', 1:3)] и unlist it (привести его к одному вектору), что позволяет вам использовать UniqueN непосредственно для подсчета уникальных чисел. .

library(data.table)
setDT(dat)

dat[, total := {rows <- Reduce('&', lapply(.(p1, p2, p3), '>=', 0.05)) 
                uniqueN(unlist(.SD[rows, paste0('t', 1:3)]))}
    , by = group]



#    group id t1   p1   t2   p2   t3   p3 total
# 1:     1  1  a 0.98    b 0.02 <NA>   NA     3
# 2:     1  2  a 1.00 <NA>   NA <NA>   NA     3
# 3:     1  3  b 0.50    a 0.25    c 0.25     3
# 4:     1  4  b 0.90    c 0.10 <NA>   NA     3
# 5:     1  5  c 1.00 <NA>   NA <NA>   NA     3
0 голосов
/ 13 ноября 2018

Это должно работать для любого количества групп и любого количества пар столбцов.

dat %>%
  gather(key, value, -group, -id) %>%
  separate(key, c('key1', 'key2'), 1) %>%
  group_by(group, id, key2) %>%
  spread(key1, value) %>%
  filter(p >= 0.05) %>%
  pull(t) %>%
  n_distinct() %>% 
  mutate(dat, total = .)
0 голосов
/ 13 ноября 2018

Мы можем использовать map2 для циклического прохождения каждого из соответствующих столбцов 't' и 'p', получения подмножества столбцов в list, filter строках на основе значений 'p' столбец, pull столбец 't', получите количество различных элементов (n_distinct) и создайте новый столбец с bind_cols

library(tidyverse)
map2_int(paste0('t', 1:3), paste0('p', 1:3), ~ 
          dat %>%
             select(.x, .y)  %>% 
             filter_at(.y, all_vars(. >= 0.05)) %>%
             pull(.x) %>%
             n_distinct) %>% 
     bind_cols(dat, total = .)

и если он является «уникальным» для всех столбцов, вместо получения n_distinct для каждого столбца, unlist list, а затем применить n_distinct, а затем создать новый столбец в «dat» с mutate

map2(paste0('t', 1:3), paste0('p', 1:3), ~ 
          dat %>% 
            select(.x, .y)  %>%
            filter_at(.y, all_vars(. >= 0.05)) %>%
            pull(.x) ) %>% 
            unlist %>% 
            n_distinct %>% 
            mutate(dat, total = .)
#   group id t1   p1   t2   p2   t3   p3 total
#1     1  1  a 0.98    b 0.02 <NA>   NA     3
#2     1  2  a 1.00 <NA>   NA <NA>   NA     3
#3     1  3  b 0.50    a 0.25    c 0.25     3
#4     1  4  b 0.90    c 0.10 <NA>   NA     3
#5     1  5  c 1.00 <NA>   NA <NA>   NA     3

Обновление

Если мы сделаем group_by n_distinct, вышеприведенное может быть изменено на summarise с помощью n_distinct из «total» после группировки по «group»

map2_df(paste0('t', 1:3), paste0('p', 1:3), ~ 
      dat %>% 
         group_by(group) %>%
         select(.x, .y)  %>%
         filter_at(.y, all_vars(. >= 0.05))  %>% 
         select(-.y) %>% 
         rename_at(.x, ~ 'total')) %>% 
   summarise(total = n_distinct(total)) %>% 
   left_join(dat)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...