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
...
#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
评论
不要忘记潜在的浮点问题,尤其是对于将数字强制转换为字符串的表而言。
–哈德利
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