我有一个数字向量:

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在向量中出现的次数?

#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
...


评论


不要忘记潜在的浮点问题,尤其是对于将数字强制转换为字符串的表而言。

–哈德利
09年12月17日在18:10

很好。这些都是整数,所以在此示例中这不是真正的问题,对吗?

– Shane
09年12月17日在18:18

不完全是。该表的元素属于整数类class(table(numbers)[1]),但435是浮点数。要使其成为整数,可以使用435L。

–伊恩研究员
09年12月18日在2:11

@Ian-在这个示例中为什么435是浮点数让我感到困惑。你能澄清一下吗?谢谢。

–希瑟·史塔克(Heather Stark)
2013年1月31日13:52

为什么不使用a [“ 435”]代替a [names(a)== 435]?

–pomber
2014年12月26日在17:08

#2 楼

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

numbers == x创建一个逻辑向量,该逻辑向量在x出现的每个位置均为TRUE,并且在sum ing时,该逻辑向量被强制转换为数值,从而将TRUE转换为1,将FALSE转换为0。 br />但是请注意,对于浮点数,最好使用类似以下内容:sum(abs(numbers - x) < 1e-6)

评论


关于浮点问题的要点。那咬我的屁股比我通常想承认的要多。

–JD Long
09年12月17日在18:13

@Jason虽然确实可以直接回答问题,但我猜想人们会喜欢更通用的解决方案,它为数据中的所有x提供答案,而不是x的特定已知值。公平地说,这就是最初的问题。正如我在下面的回答中所说的:“我发现很少想知道一个值而不是所有值的频率...”

– JBecker
13年4月22日在20:46

#3 楼

我可能会做这样的事情

length(which(numbers==x))


但是,实际上,更好的方法是

table(numbers)


评论


table(numbers)将比最简单的解决方案sum(numbers == x)做更多的工作,因为它还将计算列表中所有其他数字的计数。

–肯·威廉姆斯
09年12月18日在19:41

表的问题在于,将表包含到更复杂的演算中比较困难,例如,在数据帧上使用apply()

– skan
2015年12月2日,12:16

#4 楼

还有来自count(numbers)软件包的plyr。我认为比table方便得多。

#5 楼

我的首选解决方案使用rle,它将返回一个值(示例中为x的标签)和一个长度,该长度表示该值按顺序出现的次数。有一种非常快速的方法来计算任何值出现的次数。这对于解决更复杂的问题可能会有所帮助。

示例:

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


如果所需的值没有显示出来,或者您需要要存储该值以供以后使用,请将rle设为sort

> 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似乎是获得计数并将其全部存储的最快方法。

评论


vs表的优点是,它以更易于使用的格式提供结果吗?谢谢

–希瑟·史塔克(Heather Stark)
2013年1月31日13:54

@HeatherStark我想说有两个优点。首先肯定是它是比表输出更易于使用的格式。第二个是有时我想“连续”而不是整个数据集中的元素数量。例如,c(rep('A',3),rep('G',4),'A',rep('G',2),rep('C',10))将返回值= c ('A','G','A','G','C')和length = c(3,4,1,2,10)有时是有用的。

– JBecker
13年4月22日在20:42



使用微基准,当向量较长时(我尝试100000),表看起来更快;而当向量较短时(我尝试1000),表变得更快。

– ClementWalter
16年6月21日在16:54

如果您有很多数字,这将非常缓慢。

– skan
16 Dec 13'在19:46

#6 楼

R中有一个针对该功能的标准功能

tabulate(numbers)

评论


制表的缺点是您不能处理零和负数。

–omar
16-6-1,15:55



但是您可以处理给定数字的零个实例,而其他解决方案则无法处理

–道奇
17年1月31日,0:26

出奇的快!正如omar所说,它为未出现的值提供零计数,这在我们要建立频率分布时非常有用。零或负整数可以通过在使用表格之前添加常量来处理。注意:sort通常对于正确使用它是必需的:tabulate(sort(numbers))。

–pglpm
19年7月5日在8:36

#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 楼

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

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


#9 楼

如果要随后计算出场次数,可以使用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


评论


这绝对比表格快吗?

–加里尼
18年5月30日在13:24

#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 =名称,频率= s,stringsAsFactors = F,row.names = 1:长度))


此处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进行比较:当您多次使用不同元素的计数时,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 <-if(is.factor(x))x [!duplicated(x)] else unique(x)可以对因子输入的性能进行一些改进。

–塔兹
5月25日14:00

#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中的微基准测试,其中提出了一些建议的功能:重要的是,唯一也计算缺失值数量NA的函数是plyr::count。这些也可以使用sum(is.na(vec))
单独获得

#16 楼

一种选择是使用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


#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 楼

可以使用outer来获得相等的metrix,紧接着是rowSums,具有明显的含义。
为了使计数和numbers处于同一数据集中,首先创建一个data.frame。如果要单独的输入和输出,则不需要此步骤。

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


#19 楼

您可以创建一个函数以提供结果。
# 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