【问题标题】:Count unique values for every column计算每列的唯一值
【发布时间】:2014-04-07 09:53:26
【问题描述】:

我想返回数据框中每一列的唯一(不同)值的计数。例如,如果我有桌子:

 Testdata <- data.frame(var_1 = c("a","a","a"), var_2 = c("b","b","b"), var_3 = c("c","d","e"))

 var_1 | var_2 | var_3
 a     | b     | c 
 a     | b     | d
 a     | b     | e

我希望输出是:

 Variable | Unique_Values
 var_1    | 1
 var_2    | 1
 var_3    | 3

我尝试过使用独特的功能来玩循环,例如

 for(i in names(Testdata)){
    # Code using unique function
 }

不过我怀疑有更简单的方法。

【问题讨论】:

    标签: r dataframe count unique


    【解决方案1】:

    collapse::fNdistinct 接受data.frame

    library(collapse)
    fNdistinct(Testdata)
    # var_1 var_2 var_3 
    #     1     1     3
    

    而且速度很快。 10000 行 10000 列的数据:

    Testdata = data.frame(replicate(1e4, sample(letters[1:sample(26, 1)], 1e4, replace = TRUE)))
    system.time(fNdistinct(Testdata))
    # user  system elapsed 
    # 0.38    0.00    0.37
    

    【讨论】:

      【解决方案2】:

      使用lengths函数:

      lengths(lapply(Testdata, unique))
      
      # var_1 var_2 var_3 
      #     1     1     3 
      

      【讨论】:

        【解决方案3】:

        dplyr:

        Testdata %>% summarise_all(n_distinct)
        

        ?

        (对于那些对完整语法感到好奇的人。

        dplyr &gt;0.8.0 中使用purrr 语法:

        Testdata %>% summarise_all(list(~n_distinct(.)))
        

        dplyr &lt;0.8.0:

        Testdata %>% summarise_all(funs(n_distinct(.)))
        

        )

        有关汇总多个列的更多信息,请点击此处:https://dplyr.tidyverse.org/reference/summarise_all.html

        【讨论】:

          【解决方案4】:
          library(purrr)
          Testdata %>% map_dbl(n_distinct)
          var_1 var_2 var_3 
              1     1     3 
          
          # in your format
          Testdata %>% map_dbl(n_distinct)%>%melt(value.name = "unique_counts")
                unique_counts
          var_1             1
          var_2             1
          var_3             3
          

          【讨论】:

          • 虽然这可能会回答作者的问题,但它缺少一些解释性文字和/或文档链接。如果没有围绕它们的一些短语,原始代码 sn-ps 并不是很有帮助。您可能还会发现how to write a good answer 非常有帮助。请编辑您的答案。
          【解决方案5】:

          你可以使用apply:

          apply(Testdata, 2, function(x) length(unique(x)))
          # var_1 var_2 var_3 
          #     1     1     3
          

          【讨论】:

          • @user2721117,我建议将lapply 优于apply 作为一种扩展性更好的方法。例如lapply(Testdata, function(x) length(unique(x))。一些更大的测试数据:Testdata &lt;- data.frame(replicate(15, sample(letters[1:sample(26, 1)], 1e6, replace = TRUE)))
          【解决方案6】:

          我刚刚尝试了所有解决方案,上述两个解决方案不适用于聚合和 tidyr 解决方案,但其中两个使用无效。我认为使用数据表是一个不错的选择,

          setDT(Testdata)[, lapply(.SD, uniqueN), .SDcols=c("var_1","var_2","var_3")]
             #    var_1 var_2 var_3
             # 1:     1     1     3
          

          我试图将它们相互比较

          library(microbenchmark)
          Mycomp = microbenchmark(
            apply = apply(Testdata, 2, function(x)length(unique(x))),
            lapply = lapply(Testdata, function(x)length(unique(x))),
            sapply = sapply(Testdata, function(x)length(unique(x))),
            #base = aggregate(values ~ ind, unique(stack(Testdata)), length),
            datatable = setDT(Testdata)[, lapply(.SD, uniqueN), .SDcols=c("var_1","var_2","var_3")],
            times=50
          )
          
          #Unit: microseconds
          #      expr     min      lq     mean   median      uq     max neval cld
          #     apply 163.315 176.678 192.0435 181.7915 192.047 608.859    50  b 
          #    lapply 138.217 147.339 157.9684 153.0640 165.829 254.145    50 a  
          #    sapply 160.338 169.124 178.1486 174.3965 185.548 203.419    50  b 
          # datatable 667.937 684.650 698.1306 696.0160 703.390 874.073    50   c
          

          【讨论】:

            【解决方案7】:

            在这里,我使用dplyrtidyr 进行计数(使用您的Testdata 数据框):

            Testdata %>% 
              gather(var, value) %>% 
              distinct() %>% 
              count(var)
            
            # # A tibble: 3 × 2
            #     var     n
            #   <chr> <int>
            # 1 var_1     1
            # 2 var_2     1
            # 3 var_3     3
            

            【讨论】:

              【解决方案8】:

              这实际上是对@Ananda Mahto 评论的改进。它不适合评论,所以我决定添加作为答案。

              sapply 实际上比lapply 稍微快一点,并且以更紧凑的形式给出输出,就像apply 的输出一样。

              实际数据的测试运行结果:

              > start <- Sys.time()
              > apply(datafile, 2, function(x)length(unique(x)))
                        symbol.           date     volume 
                           1371            261      53647 
              > Sys.time() - start
              Time difference of 1.619567 secs
              > 
              > start <- Sys.time()
              > lapply(datafile, function(x)length(unique(x)))
              $symbol.
              [1] 1371
              
              $date
              [1] 261
              
              $volume
              [1] 53647
              
              > Sys.time() - start
              Time difference of 0.07129478 secs
              > 
              > start <- Sys.time()
              > sapply(datafile, function(x)length(unique(x)))
                        symbol.              date             volume 
                           1371               261              53647 
              > Sys.time() - start
              Time difference of 0.06939292 secs
              

              datafile 有大约 350 万行。

              引用帮助文本:

              sapply 是一个用户友好的版本,默认情况下是 lapply 的包装器 返回一个向量、矩阵,或者如果简化 = "array",则返回一个数组 适当的,通过应用 simple2array()。 sapply(x, f, 简化 = FALSE, USE.NAMES = FALSE) 与 lapply(x, f) 相同。

              【讨论】:

                【解决方案9】:

                这里有一个替代方案:

                aggregate(values ~ ind, unique(stack(Testdata)), length)
                #     ind values
                # 1 var_1      1
                # 2 var_2      1
                # 3 var_3      3
                

                这要求列是character

                【讨论】:

                  猜你喜欢
                  • 2020-10-06
                  • 1970-01-01
                  • 2016-09-02
                  • 1970-01-01
                  • 2021-11-12
                  • 1970-01-01
                  • 2021-03-16
                  • 1970-01-01
                  相关资源
                  最近更新 更多