使用向量中的x值计算元素的数量

时间:2009-12-17 17:21:36

标签: r vector count r-faq

我有一个数字向量:

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

如何计算值 x 在矢量中出现的次数?

19 个答案:

答案 0 :(得分:449)

您可以使用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
...

答案 1 :(得分:239)

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

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

但请注意,对于浮点数,最好使用以下内容:sum(abs(numbers - x) < 1e-6)

答案 2 :(得分:50)

我可能会做这样的事情

length(which(numbers==x))

但实际上,更好的方法是

table(numbers)

答案 3 :(得分:37)

count(numbers)包中还有plyr个。在我看来比table方便得多。

答案 4 :(得分:31)

我首选的解决方案使用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似乎是获得计数并将它们全部存储起来的最快方式。

答案 5 :(得分:17)

R中有一个标准函数

tabulate(numbers)

答案 6 :(得分:9)

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

答案 7 :(得分:8)

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

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

答案 8 :(得分: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 :(得分:7)

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

length(which(numbers == 4))

答案 10 :(得分:3)

使用表但不与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)

答案 11 :(得分:2)

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

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

这会将数据集转换为factor,然后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 :(得分:2)

这是一维原子向量的非常快速的解决方案。它依赖于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

答案 13 :(得分:1)

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

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 :(得分:1)

一种在长向量上相对较快并提供方便输出的方法是使用 Name Score 0 0 A 19 Math 1 B 20 English 2 C 11 History 3 D 12 Science (请注意lengths(split(numbers, numbers))末尾的 S ):

lengths

输出只是一个命名向量。
速度似乎可以与JBecker提出的# 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 相提并论,甚至在非常长的向量上也更快。这是 R 3.6.2 中的微基准,其中包含一些建议的功能:

rle

重要的是,唯一也可以计算缺失值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 的函数是NA。这些也可以使用plyr::count

单独获得

答案 15 :(得分:1)

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

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()的输出):

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

答案 16 :(得分:1)

这是您可以使用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

答案 17 :(得分:0)

这可以通过outer来完成,以得到相等的metrix,后跟rowSums,具有明显的含义。
为了使计数和numbers位于同一数据集中,首先创建一个data.frame。如果您想要单独的输入和输出,则不需要此步骤。

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

答案 18 :(得分:0)

您可以创建一个函数以提供结果。

# 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

相关问题