【问题标题】:Count unique characters present in a group of columns计算一组列中存在的唯一字符
【发布时间】:2019-04-16 15:19:30
【问题描述】:

我有以下数据集

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))

我正在尝试计算包含多行(变量 = 'group')的组中多列(t1、t2、t3)中存在的唯一字符数。是否计算每个字符取决于相关的 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))

但是,我要做的是计算所有列中唯一字符的总数。换句话说,如果在 t1 列中看到“a”,则不要在其他列 (t2,t3) 中计算“a”。最终产品将类似于以下数据集,其中“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))

感谢您的帮助

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    我们可以使用map2循环遍历对应的't'和'p'列,根据'p'的值得到listfilter行中的列子集列,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,而是unlistlist,然后应用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_byn_distinct,上面可以通过'group'分组后summariseing'total'的n_distinct来改变

    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)
    

    【讨论】:

      【解决方案2】:

      首先lapply 通过p 列与函数&gt;= 0.05,然后选择结果为真的所有p 列与Reduce('&amp;' 的行。获得行后,您可以使用.SD[rows, paste0('t', 1:3)]unlist 选择要计算唯一性的数据(将其强制为单个向量),这样您就可以直接使用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
      

      【讨论】:

        【解决方案3】:

        这应该适用于任意数量的组和任意数量的列对。

        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 = .)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-04-07
          • 1970-01-01
          • 1970-01-01
          • 2019-05-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多