Het aantal elementen tellen met de waarden van x in een vector

Ik heb een vector van getallen:

numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435,
         453,435,324,34,456,56,567,65,34,435)

Hoe kan ik R het aantal keren laten tellen dat een waarde xin de vector voorkomt?


Antwoord 1, autoriteit 100%

Je kunt gewoon table()gebruiken:

> 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 

Dan kun je het subsetten:

> a[names(a)==435]
435 
  3

Of converteer het naar een data.frame als u daar meer vertrouwd mee bent:

> as.data.frame(table(numbers))
   numbers Freq
1        4    2
2        5    1
3       23    2
4       34    2
...

Antwoord 2, autoriteit 50%

De meest directe manier is sum(numbers == x).

numbers == xcreëert een logische vector die WAAR is op elke locatie waar x voorkomt, en wanneer suming, wordt de logische vector gedwongen tot numeriek wat WAAR converteert naar 1 en ONWAAR naar 0.

Houd er echter rekening mee dat het voor getallen met drijvende komma beter is om zoiets te gebruiken als: sum(abs(numbers - x) < 1e-6).


Antwoord 3, autoriteit 13%

Ik zou waarschijnlijk zoiets doen

length(which(numbers==x))

Maar echt, een betere manier is

table(numbers)

4, Autoriteit 6%

My Preferred Solution gebruikt rle, die een waarde retourneert (het etiket, xin uw voorbeeld) en een lengte, die weergeeft hoe vaak die waarde verscheen volgorde.

Door rlete combineren met sort, hebt u een extreem snelle manier om het aantal keren dat elke waarde verscheen is. Dit kan nuttig zijn met meer complexe problemen.

Voorbeeld:

> 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 ...

Als de waarde die u wilt niet verschijnt, of u die waarde voor later wilt opslaan, maakt u aA 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

Ik vind het zeldzaam dat ik de frequentie van één waarde wil weten en niet alle waarden, en Rle lijkt de snelste manier te zijn om te tellen en ze allemaal op te slaan.


5, Autoriteit 4%

Er is een standaardfunctie in R voor dat

tabulate(numbers)


6, Autoriteit 2%

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

7, Autoriteit 2%

Als u het aantal verschijningen vervolgens wilt tellen, kunt u gebruik maken van de sapplyfunctie:

index<-sapply(1:length(numbers),function(x)sum(numbers[1:x]==numbers[x]))
cbind(numbers, index)

Uitgang:

       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

8, Autoriteit 2%

Hier is een snelle en vuile manier:

x <- 23
length(subset(numbers, numbers==x))

9

U kunt het nummer wijzigen in wat u wenst in de volgende lijn

length(which(numbers == 4))

Antwoord 10

Een andere manier die ik handig vind, is:

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)))

Dit converteert de dataset naar factor, en vervolgens geeft samenvatting() ons de controletotalen (tellingen van de unieke waarden).

Uitvoer is:

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 

Dit kan indien gewenst als dataframe worden opgeslagen.

as.data.frame(cbind(Number = name(s),Freq = s), stringsAsFactors=F, row.names = 1:length(s))

hier is row.names gebruikt om rijnamen te hernoemen.
zonder gebruik te maken van row.names, worden kolomnamen in s gebruikt als rijnamen in een nieuw dataframe

Uitvoer is:

    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

Antwoord 11

Tabel gebruiken maar niet vergelijken met 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 

tableis handig wanneer u de tellingen van verschillende elementen meerdere keren gebruikt. Als je maar één telling nodig hebt, gebruik dan sum(numbers == x)


Antwoord 12

Er zijn verschillende manieren om een bepaald element te tellen

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']])

Antwoord 13

Dit is een zeer snelle oplossing voor eendimensionale atomaire vectoren. Het is gebaseerd op match(), dus het is compatibel met 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

U kunt het algoritme ook aanpassen zodat het niet unique()uitvoert.

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 gevallen waar die uitvoer wenselijk is, heb je deze waarschijnlijk niet eens nodig om de originele vector terug te geven, en de tweede kolom is waarschijnlijk alles wat je nodig hebt. Je kunt dat in één regel krijgen met de pijp:

match(x, x) %>% `[`(tabulate(.), .)
#> [1] 3 2 3 2 3 1 2 2

Antwoord 14

Een methode die relatief snel is op lange vectoren en een gemakkelijke uitvoer geeft, is het gebruik van lengths(split(numbers, numbers))(let op de Saan het einde van 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 

De uitvoer is gewoon een benoemde vector.
De snelheid lijkt vergelijkbaar met rlevoorgesteld door JBeckeren zelfs een beetje sneller op zeer lange vectoren. Hier is een microbenchmark in R 3.6.2met enkele van de voorgestelde functies:

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  

Belangrijk is dat de enige functie die ook het aantal ontbrekende waarden NAtelt, is plyr::count. Deze kunnen ook afzonderlijk worden verkregen met sum(is.na(vec))


Antwoord 15

Een optie zou kunnen zijn om de functie vec_count()te gebruiken uit de bibliotheek 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

De standaardvolgorde plaatst de meest voorkomende waarden bovenaan. Als u zoekt naar sorteren op sleutels (een table()-achtige uitvoer):

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

Antwoord 16

Hier is een manier om het met dplyr te doen:

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

Antwoord 17

Dit kan gedaan worden met outerom een metriek van gelijkheden te krijgen, gevolgd door rowSums, met een voor de hand liggende betekenis.
Om de tellingen en numbersin dezelfde dataset te hebben, wordt eerst een data.frame gemaakt. Deze stap is niet nodig als u aparte invoer en uitvoer wilt.

df <- data.frame(No = numbers)
df$count <- rowSums(outer(df$No, df$No, FUN = `==`))

Antwoord 18

Je kunt een functie maken om je resultaten te geven.

# 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)

resultaat: 2

Other episodes