【问题标题】:Counting the number of elements with the values of x in a vector计算向量中具有 x 值的元素的数量
【发布时间】:2010-12-27 18:05:00
【问题描述】:

我有一个数字向量:

numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435,
         453,435,324,34,456,56,567,65,34,435)

如何让 R 计算一个值 x 在向量中出现的次数?

【问题讨论】:

    标签: r vector count r-faq


    【解决方案1】:

    你可以使用table():

    > a <- table(numbers)
    > a
    numbers
      4   5  23  34  43  54  56  65  67 324 435 453 456 567 657 
      2   1   2   2   1   1   2   1   2   1   3   1   1   1   1 
    

    然后您可以对其进行子集化:

    > a[names(a)==435]
    435 
      3
    

    如果您更愿意使用它,也可以将其转换为 data.frame:

    > as.data.frame(table(numbers))
       numbers Freq
    1        4    2
    2        5    1
    3       23    2
    4       34    2
    ...
    

    【讨论】:

    • 不要忘记潜在的浮点问题,尤其是表格,它将数字强制转换为字符串。
    【解决方案2】:

    最直接的方法是sum(numbers == x)

    numbers == x 创建一个逻辑向量,在 x 出现的每个位置都为 TRUE,当 suming 时,逻辑向量被强制转换为将 TRUE 转换为 1 和 FALSE 为 0 的数字。

    但是,请注意,对于浮点数,最好使用类似:sum(abs(numbers - x) &lt; 1e-6)

    【讨论】:

      【解决方案3】:

      我可能会做这样的事情

      length(which(numbers==x))
      

      但实际上,更好的方法是

      table(numbers)
      

      【讨论】:

      • table(numbers) 将比最简单的解决方案 sum(numbers==x) 做更多的工作,因为它还将计算列表中所有其他数字的计数。
      • 表格的问题在于它更难将其包含在更复杂的演算中,例如在数据帧上使用 apply()
      【解决方案4】:

      还有来自plyr 包的count(numbers)。在我看来,比table 方便得多。

      【讨论】:

        【解决方案5】:

        我首选的解决方案使用rle,它将返回一个值(在您的示例中为标签x)和一个长度,该长度表示该值按顺序出现的次数。

        通过将rlesort 结合使用,您可以非常快速地计算任何值出现的次数。这有助于解决更复杂的问题。

        例子:

        > numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435,453,435,324,34,456,56,567,65,34,435)
        > a <- rle(sort(numbers))
        > a
          Run Length Encoding
            lengths: int [1:15] 2 1 2 2 1 1 2 1 2 1 ...
            values : num [1:15] 4 5 23 34 43 54 56 65 67 324 ...
        

        如果您想要的值未显示,或者您需要存储该值以备后用,请将a 设为data.frame

        > b <- data.frame(number=a$values, n=a$lengths)
        > b
            values n
         1       4 2
         2       5 1
         3      23 2
         4      34 2
         5      43 1
         6      54 1
         7      56 2
         8      65 1
         9      67 2
         10    324 1
         11    435 3
         12    453 1
         13    456 1
         14    567 1
         15    657 1
        

        我发现我很少想知道一个值而不是所有值的频率,而 rle 似乎是获取计数并将它们全部存储的最快方法。

        【讨论】:

          【解决方案6】:

          R 中有一个标准函数

          tabulate(numbers)

          【讨论】:

            【解决方案7】:
            numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435 453,435,324,34,456,56,567,65,34,435)
            
            > length(grep(435, numbers))
            [1] 3
            
            
            > length(which(435 == numbers))
            [1] 3
            
            
            > require(plyr)
            > df = count(numbers)
            > df[df$x == 435, ] 
                 x freq
            11 435    3
            
            
            > sum(435 == numbers)
            [1] 3
            
            
            > sum(grepl(435, numbers))
            [1] 3
            
            
            > sum(435 == numbers)
            [1] 3
            
            
            > tabulate(numbers)[435]
            [1] 3
            
            
            > table(numbers)['435']
            435 
              3 
            
            
            > length(subset(numbers, numbers=='435')) 
            [1] 3
            

            【讨论】:

              【解决方案8】:

              如果要统计后续出现的次数,可以使用sapply函数:

              index<-sapply(1:length(numbers),function(x)sum(numbers[1:x]==numbers[x]))
              cbind(numbers, index)
              

              输出:

                      numbers index
               [1,]       4     1
               [2,]      23     1
               [3,]       4     2
               [4,]      23     2
               [5,]       5     1
               [6,]      43     1
               [7,]      54     1
               [8,]      56     1
               [9,]     657     1
              [10,]      67     1
              [11,]      67     2
              [12,]     435     1
              [13,]     453     1
              [14,]     435     2
              [15,]     324     1
              [16,]      34     1
              [17,]     456     1
              [18,]      56     2
              [19,]     567     1
              [20,]      65     1
              [21,]      34     2
              [22,]     435     3
              

              【讨论】:

                【解决方案9】:

                这是一种快速而肮脏的方法:

                x <- 23
                length(subset(numbers, numbers==x))
                

                【讨论】:

                  【解决方案10】:

                  您可以在下一行中将数​​字更改为您想要的任何值

                  length(which(numbers == 4))
                  

                  【讨论】:

                    【解决方案11】:

                    我觉得方便的另一种方法是:

                    numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435,453,435,324,34,456,56,567,65,34,435)
                    (s<-summary (as.factor(numbers)))
                    

                    这会将数据集转换为因子,然后 summary() 为我们提供控制总数(唯一值的计数)。

                    输出是:

                    4   5  23  34  43  54  56  65  67 324 435 453 456 567 657 
                    2   1   2   2   1   1   2   1   2   1   3   1   1   1   1 
                    

                    如果愿意,可以将其存储为数据框。

                    as.data.frame(cbind(Number = names(s),Freq = s), stringsAsFactors=F, row.names = 1:length(s))

                    这里的 row.names 被用来重命名行名。 在不使用 row.names 的情况下,s 中的列名用作新数据框中的行名

                    输出是:

                         Number Freq
                    1       4    2
                    2       5    1
                    3      23    2
                    4      34    2
                    5      43    1
                    6      54    1
                    7      56    2
                    8      65    1
                    9      67    2
                    10    324    1
                    11    435    3
                    12    453    1
                    13    456    1
                    14    567    1
                    15    657    1
                    

                    【讨论】:

                      【解决方案12】:

                      使用表格但不与names比较:

                      numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435)
                      x <- 67
                      numbertable <- table(numbers)
                      numbertable[as.character(x)]
                      #67 
                      # 2 
                      

                      table 在您多次使用不同元素的计数时很有用。如果您只需要一个计数,请使用sum(numbers == x)

                      【讨论】:

                        【解决方案13】:

                        计算特定元素有不同的方法

                        library(plyr)
                        numbers =c(4,23,4,23,5,43,54,56,657,67,67,435,453,435,7,65,34,435)
                        
                        print(length(which(numbers==435)))
                        
                        #Sum counts number of TRUE's in a vector 
                        print(sum(numbers==435))
                        print(sum(c(TRUE, FALSE, TRUE)))
                        
                        #count is present in plyr library 
                        #o/p of count is a DataFrame, freq is 1 of the columns of data frame
                        print(count(numbers[numbers==435]))
                        print(count(numbers[numbers==435])[['freq']])
                        

                        【讨论】:

                          【解决方案14】:

                          对于一维原子向量,这是一个非常快速的解决方案。它依赖match(),所以兼容NA

                          x <- c("a", NA, "a", "c", "a", "b", NA, "c")
                          
                          fn <- function(x) {
                            u <- unique.default(x)
                            out <- list(x = u, freq = .Internal(tabulate(match(x, u), length(u))))
                            class(out) <- "data.frame"
                            attr(out, "row.names") <- seq_along(u)
                            out
                          }
                          
                          fn(x)
                          
                          #>      x freq
                          #> 1    a    3
                          #> 2 <NA>    2
                          #> 3    c    2
                          #> 4    b    1
                          

                          您还可以调整算法,使其不运行unique()

                          fn2 <- function(x) {
                            y <- match(x, x)
                            out <- list(x = x, freq = .Internal(tabulate(y, length(x)))[y])
                            class(out) <- "data.frame"
                            attr(out, "row.names") <- seq_along(x)
                            out
                          }
                          
                          fn2(x)
                          
                          #>      x freq
                          #> 1    a    3
                          #> 2 <NA>    2
                          #> 3    a    3
                          #> 4    c    2
                          #> 5    a    3
                          #> 6    b    1
                          #> 7 <NA>    2
                          #> 8    c    2
                          

                          在需要该输出的情况下,您甚至可能不需要它来重新返回原始向量,而第二列可能就是您所需要的。你可以用管道在一行中得到它:

                          match(x, x) %>% `[`(tabulate(.), .)
                          
                          #> [1] 3 2 3 2 3 1 2 2
                          

                          【讨论】:

                          • 非常棒的解决方案!这也是我能想到的最快的一个。使用 u
                          【解决方案15】:

                          在长向量上相对较快并提供方便输出的方法是使用lengths(split(numbers, numbers))(注意lengths末尾的S):

                          # Make some integer vectors of different sizes
                          set.seed(123)
                          x <- sample.int(1e3, 1e4, replace = TRUE)
                          xl <- sample.int(1e3, 1e6, replace = TRUE)
                          xxl <-sample.int(1e3, 1e7, replace = TRUE)
                          
                          # Number of times each value appears in x:
                          a <- lengths(split(x,x))
                          
                          # Number of times the value 64 appears:
                          a["64"]
                          #~ 64
                          #~ 15
                          
                          # Occurences of the first 10 values
                          a[1:10]
                          #~ 1  2  3  4  5  6  7  8  9 10 
                          #~ 13 12  6 14 12  5 13 14 11 14 
                          

                          输出只是一个命名向量。
                          速度似乎与JBecker 提出的rle 相当,甚至在非常长的向量上还要快一些。这是 R 3.6.2 中的一个微基准测试,其中包含一些建议的功能:

                          library(microbenchmark)
                          
                          f1 <- function(vec) lengths(split(vec,vec))
                          f2 <- function(vec) table(vec)
                          f3 <- function(vec) rle(sort(vec))
                          f4 <- function(vec) plyr::count(vec)
                          
                          microbenchmark(split = f1(x),
                                         table = f2(x),
                                         rle = f3(x),
                                         plyr = f4(x))
                          #~ Unit: microseconds
                          #~   expr      min        lq      mean    median        uq      max neval  cld
                          #~  split  402.024  423.2445  492.3400  446.7695  484.3560 2970.107   100  b  
                          #~  table 1234.888 1290.0150 1378.8902 1333.2445 1382.2005 3203.332   100    d
                          #~    rle  227.685  238.3845  264.2269  245.7935  279.5435  378.514   100 a   
                          #~   plyr  758.866  793.0020  866.9325  843.2290  894.5620 2346.407   100   c 
                          
                          microbenchmark(split = f1(xl),
                                         table = f2(xl),
                                         rle = f3(xl),
                                         plyr = f4(xl))
                          #~ Unit: milliseconds
                          #~   expr       min        lq      mean    median        uq       max neval cld
                          #~  split  21.96075  22.42355  26.39247  23.24847  24.60674  82.88853   100 ab 
                          #~  table 100.30543 104.05397 111.62963 105.54308 110.28732 168.27695   100   c
                          #~    rle  19.07365  20.64686  23.71367  21.30467  23.22815  78.67523   100 a  
                          #~   plyr  24.33968  25.21049  29.71205  26.50363  27.75960  92.02273   100  b 
                          
                          microbenchmark(split = f1(xxl),
                                         table = f2(xxl),
                                         rle = f3(xxl),
                                         plyr = f4(xxl))
                          #~ Unit: milliseconds
                          #~   expr       min        lq      mean    median        uq       max neval  cld
                          #~  split  296.4496  310.9702  342.6766  332.5098  374.6485  421.1348   100 a   
                          #~  table 1151.4551 1239.9688 1283.8998 1288.0994 1323.1833 1385.3040   100    d
                          #~    rle  399.9442  430.8396  464.2605  471.4376  483.2439  555.9278   100   c 
                          #~   plyr  350.0607  373.1603  414.3596  425.1436  437.8395  506.0169   100  b  
                          

                          重要的是,唯一同时计算缺失值数量的函数NAplyr::count。这些也可以使用sum(is.na(vec))单独获取

                          【讨论】:

                            【解决方案16】:

                            一种选择是使用vctrs 库中的vec_count() 函数:

                            vec_count(numbers)
                            
                               key count
                            1  435     3
                            2   67     2
                            3    4     2
                            4   34     2
                            5   56     2
                            6   23     2
                            7  456     1
                            8   43     1
                            9  453     1
                            10   5     1
                            11 657     1
                            12 324     1
                            13  54     1
                            14 567     1
                            15  65     1
                            

                            默认排序将最常见的值放在顶部。如果要根据键进行排序(table()-like 输出):

                            vec_count(numbers, sort = "key")
                            
                               key count
                            1    4     2
                            2    5     1
                            3   23     2
                            4   34     2
                            5   43     1
                            6   54     1
                            7   56     2
                            8   65     1
                            9   67     2
                            10 324     1
                            11 435     3
                            12 453     1
                            13 456     1
                            14 567     1
                            15 657     1
                            

                            【讨论】:

                              【解决方案17】:

                              这是您可以使用 dplyr 实现的一种方法:

                              library(tidyverse)
                              
                              numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435,
                                           453,435,324,34,456,56,567,65,34,435)
                              ord <- seq(1:(length(numbers)))
                              
                              df <- data.frame(ord,numbers)
                              
                              df <- df %>%
                                count(numbers)
                              
                              numbers     n
                                   <dbl> <int>
                               1       4     2
                               2       5     1
                               3      23     2
                               4      34     2
                               5      43     1
                               6      54     1
                               7      56     2
                               8      65     1
                               9      67     2
                              10     324     1
                              11     435     3
                              12     453     1
                              13     456     1
                              14     567     1
                              15     657     1
                              

                              【讨论】:

                                【解决方案18】:

                                2021年Base r解决方案

                                aggregate(numbers, list(num=numbers), length)
                                
                                       num x
                                1        4 2
                                2        5 1
                                3       23 2
                                4       34 2
                                5       43 1
                                6       54 1
                                7       56 2
                                8       65 1
                                9       67 2
                                10     324 1
                                11     435 3
                                12     453 1
                                13     456 1
                                14     567 1
                                15     657 1
                                
                                tapply(numbers, numbers, length)
                                  4   5  23  34  43  54  56  65  67 324 435 453 456 567 657 
                                  2   1   2   2   1   1   2   1   2   1   3   1   1   1   1 
                                
                                by(numbers, list(num=numbers), length)
                                num: 4
                                [1] 2
                                -------------------------------------- 
                                num: 5
                                [1] 1
                                -------------------------------------- 
                                num: 23
                                [1] 2
                                -------------------------------------- 
                                num: 34
                                [1] 2
                                -------------------------------------- 
                                num: 43
                                [1] 1
                                -------------------------------------- 
                                num: 54
                                [1] 1
                                -------------------------------------- 
                                num: 56
                                [1] 2
                                -------------------------------------- 
                                num: 65
                                [1] 1
                                -------------------------------------- 
                                num: 67
                                [1] 2
                                -------------------------------------- 
                                num: 324
                                [1] 1
                                -------------------------------------- 
                                num: 435
                                [1] 3
                                -------------------------------------- 
                                num: 453
                                [1] 1
                                -------------------------------------- 
                                num: 456
                                [1] 1
                                -------------------------------------- 
                                num: 567
                                [1] 1
                                -------------------------------------- 
                                num: 657
                                [1] 1
                                
                                

                                【讨论】:

                                  【解决方案19】:

                                  这可以用outer 来完成,得到一个等式矩阵,然后是rowSums,含义很明显。
                                  为了使计数和numbers 在同一个数据集中,首先创建一个 data.frame。如果您想要单独的输入和输出,则不需要此步骤。

                                  df <- data.frame(No = numbers)
                                  df$count <- rowSums(outer(df$No, df$No, FUN = `==`))
                                  

                                  【讨论】:

                                    【解决方案20】:

                                    你可以创建一个函数来给你结果。

                                    # your list
                                    numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435,
                                             453,435,324,34,456,56,567,65,34,435)
                                    
                                    function1<-function(x){
                                        if(x==value){return(1)}else{ return(0) }
                                    }
                                    
                                    # set your value here
                                    value<-4
                                    
                                    # make a vector which return 1 if it equal to your value, 0 else
                                    vector<-sapply(numbers,function(x) function1(x))
                                    sum(vector)
                                    

                                    结果:2

                                    【讨论】:

                                      猜你喜欢
                                      • 1970-01-01
                                      • 2014-02-27
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2015-04-18
                                      相关资源
                                      最近更新 更多