Antworten:
Sie können einfach verwenden 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
Dann können Sie es unterteilen:
> a[names(a)==435]
435
3
Oder konvertieren Sie es in einen data.frame, wenn Sie damit besser arbeiten können:
> as.data.frame(table(numbers))
numbers Freq
1 4 2
2 5 1
3 23 2
4 34 2
...
a["435"]
anstelle von a[names(a)==435]
?
Der direkteste Weg ist sum(numbers == x)
.
numbers == x
Erstellt einen logischen Vektor, der an jeder Stelle, an der x auftritt, WAHR ist, und wenn er ausgeführt wird sum
, wird der logische Vektor in einen numerischen Vektor gezwungen, der WAHR in 1 und FALSCH in 0 konvertiert.
Beachten Sie jedoch, dass es für Gleitkommazahlen besser ist, Folgendes zu verwenden : sum(abs(numbers - x) < 1e-6)
.
x
in den Daten liefert, anstatt einen bestimmten bekannten Wert von x
. Um fair zu sein, darum ging es in der ursprünglichen Frage. Wie ich in meiner Antwort unten sagte: "Ich finde, es ist selten, dass ich die Häufigkeit eines Wertes und nicht aller Werte wissen möchte ..."
Ich würde wahrscheinlich so etwas tun
length(which(numbers==x))
Aber wirklich, ein besserer Weg ist
table(numbers)
table(numbers)
wird viel mehr Arbeit leisten als die einfachste Lösung, sum(numbers==x)
weil es auch die Anzahl aller anderen Zahlen in der Liste herausfinden wird.
Es gibt auch count(numbers)
aus plyr
Paket. Viel bequemer als table
meiner Meinung nach.
Meine bevorzugte Lösung verwendet rle
, die einen Wert ( x
in Ihrem Beispiel die Bezeichnung ) und eine Länge zurückgibt, die angibt, wie oft dieser Wert nacheinander angezeigt wurde.
Durch die Kombination rle
mit sort
haben Sie eine extrem schnelle Möglichkeit, die Häufigkeit zu zählen, mit der ein Wert angezeigt wurde. Dies kann bei komplexeren Problemen hilfreich sein.
Beispiel:
> 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 ...
Wenn der gewünschte Wert nicht angezeigt wird oder Sie diesen Wert für später speichern müssen, erstellen Sie 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
Ich finde es selten, dass ich die Häufigkeit eines Wertes und nicht aller Werte wissen möchte, und rle scheint der schnellste Weg zu sein, um alle zu zählen und zu speichern.
c(rep('A', 3), rep('G', 4), 'A', rep('G', 2), rep('C', 10))
würde zurückkehren values = c('A','G','A','G','C')
und lengths=c(3, 4, 1, 2, 10)
was manchmal nützlich ist.
table
es schneller zu sein when the vector is long
(ich habe 100000 ausprobiert), aber etwas länger, wenn es kürzer ist (ich habe 1000 ausprobiert)
Dafür gibt es in R eine Standardfunktion
tabulate(numbers)
tabulate
ist, dass Sie nicht mit Nullen und negativen Zahlen umgehen können.
tabulate
. Hinweis: sort
scheint für die korrekte Verwendung im Allgemeinen erforderlich zu sein : 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
Wenn Sie die Anzahl der Auftritte anschließend zählen möchten, können Sie die folgende sapply
Funktion verwenden:
index<-sapply(1:length(numbers),function(x)sum(numbers[1:x]==numbers[x]))
cbind(numbers, index)
Ausgabe:
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
Sie können die Nummer in der folgenden Zeile beliebig ändern
length(which(numbers == 4))
Ein weiterer Weg, den ich bequem finde, ist:
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)))
Dadurch wird der Datensatz in einen Faktor konvertiert, und dann gibt summary () die Kontrollsummen (Anzahl der eindeutigen Werte) an.
Ausgabe ist:
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
Dies kann bei Bedarf als Datenrahmen gespeichert werden.
as.data.frame (cbind (Number = names (s), Freq = s), stringsAsFactors = F, row.names = 1: length (s))
Hier wurde row.names verwendet, um Zeilennamen umzubenennen. Ohne Verwendung von row.names werden Spaltennamen in s als Zeilennamen in neuen Datenrahmen verwendet
Ausgabe ist:
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
Tabelle verwenden, aber ohne zu vergleichen mit 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
ist nützlich, wenn Sie die Anzahl der verschiedenen Elemente mehrmals verwenden. Wenn Sie nur eine Zählung benötigen, verwenden Siesum(numbers == x)
Es gibt verschiedene Möglichkeiten, bestimmte Elemente zu zählen
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']])
Eine Methode, die bei langen Vektoren relativ schnell ist und eine bequeme Ausgabe liefert, ist die Verwendung lengths(split(numbers, numbers))
(beachten Sie das S am Ende von 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
Die Ausgabe ist einfach ein benannter Vektor.
Die Geschwindigkeit scheint vergleichbar mit rle
der von JBecker vorgeschlagenen und bei sehr langen Vektoren sogar etwas schneller zu sein. Hier ist ein Mikrobenchmark in R 3.6.2 mit einigen der vorgeschlagenen Funktionen:
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
Wichtig ist, dass die einzige Funktion, die auch die Anzahl der fehlenden Werte zählt, NA
ist plyr::count
. Diese können auch separat mit bezogen werdensum(is.na(vec))
Dies ist eine sehr schnelle Lösung für eindimensionale Atomvektoren. Es match()
basiert auf , ist also kompatibel mit 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
Sie können den Algorithmus auch so anpassen, dass er nicht ausgeführt wird 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
In Fällen, in denen diese Ausgabe wünschenswert ist, benötigen Sie sie wahrscheinlich nicht einmal, um den ursprünglichen Vektor zurückzugeben, und die zweite Spalte ist wahrscheinlich alles, was Sie benötigen. Sie können das in einer Zeile mit dem Rohr erhalten:
match(x, x) %>% `[`(tabulate(.), .)
#> [1] 3 2 3 2 3 1 2 2
Dies kann getan werden outer
, um eine Metrik von Gleichheiten zu erhalten, gefolgt von rowSums
einer offensichtlichen Bedeutung.
Um die numbers
Anzahl und das gleiche Dataset zu erhalten, wird zuerst ein data.frame erstellt. Dieser Schritt ist nicht erforderlich, wenn Sie eine separate Eingabe und Ausgabe wünschen.
df <- data.frame(No = numbers)
df$count <- rowSums(outer(df$No, df$No, FUN = `==`))