Câu trả lời:
Bạn chỉ có thể sử dụng 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
Sau đó, bạn có thể đặt nó:
> a[names(a)==435]
435
3
Hoặc chuyển đổi nó thành data.frame nếu bạn cảm thấy thoải mái hơn khi làm việc với điều đó:
> as.data.frame(table(numbers))
numbers Freq
1 4 2
2 5 1
3 23 2
4 34 2
...
a["435"]
chèn vào a[names(a)==435]
?
Cách trực tiếp nhất là sum(numbers == x)
.
numbers == x
tạo ra một vectơ logic là TRUE tại mọi vị trí x xảy ra và khi sum
ing, vectơ logic được ép thành số chuyển đổi TRUE thành 1 và FALSE thành 0.
Tuy nhiên, lưu ý rằng đối với các số dấu phẩy động, tốt hơn là sử dụng cái gì đó như : sum(abs(numbers - x) < 1e-6)
.
x
trong dữ liệu hơn là một giá trị cụ thể được biết đến x
. Công bằng mà nói, đó là những gì câu hỏi ban đầu là về. Như tôi đã nói trong câu trả lời của mình dưới đây, "Tôi thấy rất hiếm khi tôi muốn biết tần số của một giá trị và không phải tất cả các giá trị ..."
Tôi có thể sẽ làm một cái gì đó như thế này
length(which(numbers==x))
Nhưng thực sự, một cách tốt hơn là
table(numbers)
table(numbers)
sẽ làm được nhiều việc hơn là giải pháp đơn giản nhất sum(numbers==x)
, bởi vì nó cũng sẽ tìm ra số đếm của tất cả các số khác trong danh sách.
Giải pháp ưa thích của tôi sử dụng rle
, sẽ trả về một giá trị (nhãn, x
trong ví dụ của bạn) và độ dài, đại diện cho số lần giá trị đó xuất hiện trong chuỗi.
Bằng cách kết hợp rle
với sort
, bạn có một cách cực kỳ nhanh chóng để đếm số lần bất kỳ giá trị nào xuất hiện. Điều này có thể hữu ích với các vấn đề phức tạp hơn.
Thí dụ:
> 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 ...
Nếu giá trị bạn muốn không hiển thị hoặc bạn cần lưu trữ giá trị đó sau, hãy tạo a
một 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
Tôi thấy hiếm khi tôi muốn biết tần số của một giá trị và không phải tất cả các giá trị, và rle dường như là cách nhanh nhất để lấy số lượng và lưu trữ tất cả.
c(rep('A', 3), rep('G', 4), 'A', rep('G', 2), rep('C', 10))
sẽ trở lại values = c('A','G','A','G','C')
và lengths=c(3, 4, 1, 2, 10)
đôi khi hữu ích.
table
nhanh hơn when the vector is long
(tôi đã thử 100000) nhưng lâu hơn một chút khi nó ngắn hơn (tôi đã thử 1000)
Có một hàm tiêu chuẩn trong R cho điều đó
tabulate(numbers)
tabulate
là bạn không thể xử lý số 0 và số âm.
tabulate
. Lưu ý: sort
dường như là cần thiết cho việc sử dụng chính xác của nó nói chung : tabulate(sort(numbers))
.
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
Nếu bạn muốn đếm số lần xuất hiện sau đó, bạn có thể sử dụng sapply
chức năng:
index<-sapply(1:length(numbers),function(x)sum(numbers[1:x]==numbers[x]))
cbind(numbers, index)
Đầu ra:
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
Bạn có thể thay đổi số thành bất cứ điều gì bạn muốn trong dòng sau
length(which(numbers == 4))
Một cách nữa tôi thấy thuận tiện là:
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)))
Điều này chuyển đổi tập dữ liệu thành yếu tố, và sau đó tóm tắt () cung cấp cho chúng ta tổng số kiểm soát (tính các giá trị duy nhất).
Đầu ra là:
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
Điều này có thể được lưu trữ dưới dạng dataframe nếu thích.
as.data.frame (cbind (Number = name (s), Freq = s), StringAsFactors = F, row.names = 1: length (s))
ở đây row.names đã được sử dụng để đổi tên tên hàng. không sử dụng row.names, tên cột trong s được sử dụng làm tên hàng trong khung dữ liệu mới
Đầu ra là:
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
Sử dụng bảng nhưng không so sánh với 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
rất hữu ích khi bạn đang sử dụng số lượng các yếu tố khác nhau nhiều lần. Nếu bạn chỉ cần một lần đếm, hãy sử dụngsum(numbers == x)
Có nhiều cách khác nhau để đếm một yếu tố cụ thể
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']])
Một phương pháp tương đối nhanh trên các vectơ dài và cho đầu ra thuận tiện là sử dụng lengths(split(numbers, numbers))
(lưu ý chữ S ở cuối lengths
):
# 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
Đầu ra chỉ đơn giản là một vector có tên.
Tốc độ xuất hiện tương đương với rle
đề xuất của JBecker và thậm chí nhanh hơn một chút trên các vectơ rất dài. Đây là một microbenchmark trong R 3.6.2 với một số chức năng được đề xuất:
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
Điều quan trọng, chức năng duy nhất cũng đếm số lượng giá trị còn thiếu NA
là plyr::count
. Chúng cũng có thể được lấy riêng bằng cách sử dụngsum(is.na(vec))
Đây là một giải pháp rất nhanh cho các vectơ nguyên tử một chiều. Nó dựa vào match()
, vì vậy nó tương thích với 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
Bạn cũng có thể điều chỉnh thuật toán để nó không chạy 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
Trong trường hợp đầu ra đó là mong muốn, bạn thậm chí không cần nó để trả lại vectơ ban đầu và cột thứ hai có lẽ là tất cả những gì bạn cần. Bạn có thể lấy nó trong một dòng với đường ống:
match(x, x) %>% `[`(tabulate(.), .)
#> [1] 3 2 3 2 3 1 2 2
Điều này có thể được thực hiện với outer
để có được một metrix công bằng theo sau rowSums
, với một ý nghĩa rõ ràng.
Để có số lượng và numbers
trong cùng một tập dữ liệu, data.frame được tạo trước tiên. Bước này là không cần thiết nếu bạn muốn đầu vào và đầu ra riêng biệt.
df <- data.frame(No = numbers)
df$count <- rowSums(outer(df$No, df$No, FUN = `==`))