Bir sayı vektörüm var:
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'nin x değerinin vektörde kaç kez göründüğünü nasıl gösterebilirim ?
Bir sayı vektörüm var:
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'nin x değerinin vektörde kaç kez göründüğünü nasıl gösterebilirim ?
Yanıtlar:
Sadece şunu kullanabilirsiniz 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
Sonra alt kümeye ayarlayabilirsiniz:
> a[names(a)==435]
435
3
Ya da bununla çalışmaktan daha rahatsanız bir data.frame'e dönüştürün:
> as.data.frame(table(numbers))
numbers Freq
1 4 2
2 5 1
3 23 2
4 34 2
...
a["435"]
inatçı değil a[names(a)==435]
?
En doğrudan yol sum(numbers == x)
.
numbers == x
x'in meydana geldiği her konumda TRUE olan bir mantıksal vektör oluşturur ve sum
ing sırasında mantıksal vektör TRUE değerini 1 ve FALSE değerini 0'a dönüştüren sayıya zorlanır.
Ancak, kayan nokta sayıları için neye kullanım şey daha iyi olacağını not: sum(abs(numbers - x) < 1e-6)
.
x
belirli bir bilinen değeri yerine tüm veriler için cevap sağlayan daha genel çözümü sevdim olduğunu x
. Adil olmak gerekirse, asıl sorunun konusu buydu. Aşağıdaki
Muhtemelen böyle bir şey yapardım
length(which(numbers==x))
Ama gerçekten, daha iyi bir yol
table(numbers)
table(numbers)
en kolay çözümden çok daha fazla iş yapacak sum(numbers==x)
, çünkü listedeki diğer tüm sayıların sayısını da çözecek.
Tercih ettiğim çözüm rle
, bir değer ( x
örneğinizdeki etiket ) ve bu değerin sırayla kaç kez göründüğünü gösteren bir uzunluk döndürecek şekilde kullanır .
Birleştirerek rle
ile sort
, herhangi bir değer görüntülenme sayısını saymak için son derece hızlı bir yol var. Bu daha karmaşık sorunlarda yardımcı olabilir.
Misal:
> 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 ...
İstediğiniz değer görünmüyorsa veya bu değeri daha sonra kullanmak üzere saklamanız gerekiyorsa, 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
Tüm değerlerin değil, bir değerin frekansını bilmek istediğimi nadir görüyorum ve rle, sayımı alıp hepsini depolamanın en hızlı yolu gibi görünüyor.
c(rep('A', 3), rep('G', 4), 'A', rep('G', 2), rep('C', 10))
geri dönecek values = c('A','G','A','G','C')
ve lengths=c(3, 4, 1, 2, 10)
bu bazen yararlı olacaktır.
table
, daha hızlı when the vector is long
(100000 denedim) ama daha kısa (1000 denedim) biraz daha uzun görünüyor
Bunun için R'de standart bir fonksiyon vardır
tabulate(numbers)
tabulate
sıfır ve negatif sayılarla başa çıkamamanızdır.
tabulate
. Not: sort
genel olarak doğru kullanımı için gerekli gibi görünüyor: 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
Daha sonra görünüm sayısını saymak isterseniz, sapply
işlevi kullanabilirsiniz :
index<-sapply(1:length(numbers),function(x)sum(numbers[1:x]==numbers[x]))
cbind(numbers, index)
Çıktı:
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
Aşağıdaki satırda numarayı istediğiniz gibi değiştirebilirsiniz
length(which(numbers == 4))
Uygun bulmanın bir yolu daha:
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)))
Bu, veri kümesini faktöre dönüştürür ve sonra özet () bize kontrol toplamlarını (benzersiz değerlerin sayısı) verir.
Çıktı:
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
İstenirse bu veri çerçevesi olarak saklanabilir.
as.data.frame (cbind (Sayı = ad (lar), Frek = s), dizelerAsFactors = F, row.names = 1: uzunluk (lar))
burada row.names, satır adlarını yeniden adlandırmak için kullanılmıştır. row.names kullanılmadan, s'deki sütun adları yeni veri çerçevesinde satır adları olarak kullanılır
Çıktı:
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
Tablo kullanarak ancak aşağıdakilerle karşılaştırmadan 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
birkaç kez farklı elemanların sayısını kullanırken faydalıdır. Yalnızca bir sayıya ihtiyacınız varsa,sum(numbers == x)
Belirli bir öğeyi saymanın farklı yolları vardır
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']])
Uzun vektörlerde nispeten hızlı olan ve uygun bir çıktı veren bir yöntem kullanmaktır lengths(split(numbers, numbers))
( sonundaki S'ye dikkat edin 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
Çıktı sadece adlandırılmış bir vektördür.
Hız rle
, JBecker tarafından önerilenle karşılaştırılabilir ve çok uzun vektörlerde biraz daha hızlı görünüyor . İşte R 3.6.2'de önerilen bazı işlevlerle birlikte bir mikrobenchmark :
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
Önemli olan, ayrıca eksik değerleri sayar tek işlevi NA
olduğunu plyr::count
. Bunlar ayrıca ayrı olarak elde edilebilirsum(is.na(vec))
Bu, tek boyutlu atom vektörleri için çok hızlı bir çözümdür. Güvenir match()
, bu nedenle aşağıdakilerle uyumludur 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
Ayrıca algoritmayı çalıştıracak şekilde değiştirebilirsiniz 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
Bu çıktının arzu edildiği durumlarda, muhtemelen orijinal vektörü yeniden döndürmek için ona ihtiyacınız yoktur ve ikinci sütun muhtemelen ihtiyacınız olan tek şeydir. Bunu boru ile bir satırda alabilirsiniz:
match(x, x) %>% `[`(tabulate(.), .)
#> [1] 3 2 3 2 3 1 2 2
Bu ile yapılabilir outer
eşitliklerin bir metrikini elde etmek için bunu rowSums
bariz bir anlamla takip eder.
Sayımlara sahip olmak ve numbers
aynı veri kümesinde, önce bir data.frame oluşturulur. Ayrı bir giriş ve çıkış istiyorsanız bu adıma gerek yoktur.
df <- data.frame(No = numbers)
df$count <- rowSums(outer(df$No, df$No, FUN = `==`))