Saya memiliki vektor angka:
numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435,
453,435,324,34,456,56,567,65,34,435)
Bagaimana saya bisa meminta R menghitung berapa kali nilai x muncul dalam vektor?
Saya memiliki vektor angka:
numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435,
453,435,324,34,456,56,567,65,34,435)
Bagaimana saya bisa meminta R menghitung berapa kali nilai x muncul dalam vektor?
Jawaban:
Anda bisa menggunakan 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
Kemudian Anda dapat mengelompokkannya:
> a[names(a)==435]
435
3
Atau mengubahnya menjadi data.frame jika Anda lebih nyaman bekerja dengan itu:
> as.data.frame(table(numbers))
numbers Freq
1 4 2
2 5 1
3 23 2
4 34 2
...
a["435"]
insetead a[names(a)==435]
?
Cara paling langsung adalah sum(numbers == x)
.
numbers == x
menciptakan vektor logis yang BENAR di setiap lokasi yang terjadi x, dan ketika sum
ing, vektor logis dipaksa untuk numerik yang mengubah BENAR ke 1 dan SALAH ke 0.
Namun, catatan bahwa untuk angka floating point lebih baik untuk penggunaan sesuatu seperti: sum(abs(numbers - x) < 1e-6)
.
x
dalam data daripada nilai yang diketahui spesifik x
. Agar adil, itulah pertanyaan aslinya. Seperti yang saya katakan dalam jawaban saya di bawah, "Saya merasa jarang saya ingin mengetahui frekuensi satu nilai dan tidak semua nilai ..."
Saya mungkin akan melakukan sesuatu seperti ini
length(which(numbers==x))
Tapi sungguh, cara yang lebih baik adalah
table(numbers)
table(numbers)
akan melakukan lebih banyak pekerjaan daripada solusi termudah sum(numbers==x)
,, karena itu akan mencari tahu jumlah semua angka lain dalam daftar juga.
Solusi pilihan saya menggunakan rle
, yang akan mengembalikan nilai (label,x
dalam contoh Anda) dan panjang, yang menunjukkan berapa kali nilai tersebut muncul secara berurutan.
Dengan menggabungkan rle
dengansort
, Anda memiliki cara yang sangat cepat untuk menghitung berapa kali nilai muncul. Ini bisa membantu dengan masalah yang lebih kompleks.
Contoh:
> 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 ...
Jika nilai yang Anda inginkan tidak muncul, atau Anda perlu menyimpan nilai itu untuk nanti, buat a
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
Saya merasa jarang bahwa saya ingin mengetahui frekuensi satu nilai dan tidak semua nilai, dan rle tampaknya menjadi cara tercepat untuk mendapatkan hitungan dan menyimpan semuanya.
c(rep('A', 3), rep('G', 4), 'A', rep('G', 2), rep('C', 10))
mau kembali values = c('A','G','A','G','C')
dan lengths=c(3, 4, 1, 2, 10)
mana yang kadang berguna.
table
lebih cepat when the vector is long
(saya mencoba 100000) tetapi sedikit lebih lama ketika lebih pendek (saya mencoba 1000)
Ada fungsi standar dalam R untuk itu
tabulate(numbers)
tabulate
adalah Anda tidak bisa berurusan dengan angka nol dan negatif.
tabulate
. Catatan: sort
tampaknya diperlukan untuk penggunaan yang benar secara umum: 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
Jika Anda ingin menghitung jumlah penampilan selanjutnya, Anda dapat menggunakan sapply
fungsi ini:
index<-sapply(1:length(numbers),function(x)sum(numbers[1:x]==numbers[x]))
cbind(numbers, index)
Keluaran:
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
Anda dapat mengubah nomornya menjadi apa pun yang Anda inginkan di baris berikut
length(which(numbers == 4))
Satu lagi cara yang menurut saya nyaman adalah:
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)))
Ini mengubah dataset menjadi faktor, dan kemudian ringkasan () memberi kita total kontrol (jumlah nilai unik).
Output adalah:
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
Ini dapat disimpan sebagai kerangka data jika diinginkan.
as.data.frame (cbind (Number = names (s), Freq = s), stringsAsFactors = F, row.names = 1: length (s))
di sini row.names telah digunakan untuk mengubah nama nama baris. tanpa menggunakan row.names, nama kolom dalam s digunakan sebagai nama baris dalam bingkai data baru
Output adalah:
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
Menggunakan tabel tetapi tanpa membandingkan dengan 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
berguna ketika Anda menggunakan jumlah elemen yang berbeda beberapa kali. Jika Anda hanya perlu satu hitungan, gunakansum(numbers == x)
Ada berbagai cara penghitungan elemen tertentu
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']])
Metode yang relatif cepat pada vektor panjang dan memberikan output yang nyaman adalah dengan menggunakan lengths(split(numbers, numbers))
(perhatikan S pada akhir 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
Outputnya hanyalah sebuah vektor bernama.
Kecepatan muncul sebanding dengan yang rle
diusulkan oleh JBecker dan bahkan sedikit lebih cepat pada vektor yang sangat panjang. Berikut ini adalah microbenchmark dalam R 3.6.2 dengan beberapa fungsi yang diusulkan:
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
Yang penting, satu-satunya fungsi yang juga menghitung jumlah nilai yang hilang NA
adalah plyr::count
. Ini juga dapat diperoleh secara terpisah menggunakansum(is.na(vec))
Ini adalah solusi yang sangat cepat untuk vektor atom satu dimensi. Itu bergantung match()
, sehingga kompatibel dengan 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
Anda juga dapat mengubah algoritme agar tidak berjalan 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
Dalam kasus di mana output itu diinginkan, Anda mungkin bahkan tidak memerlukannya untuk mengembalikan kembali vektor asli, dan kolom kedua mungkin semua yang Anda butuhkan. Anda bisa mendapatkannya dalam satu baris dengan pipa:
match(x, x) %>% `[`(tabulate(.), .)
#> [1] 3 2 3 2 3 1 2 2
Hal ini dapat dilakukan dengan outer
mendapatkan metriks kesetaraan diikuti oleh rowSums
, dengan makna yang jelas.
Untuk memiliki jumlah dan numbers
dalam dataset yang sama, sebuah data.frame pertama kali dibuat. Langkah ini tidak diperlukan jika Anda ingin input dan output terpisah.
df <- data.frame(No = numbers)
df$count <- rowSums(outer(df$No, df$No, FUN = `==`))