R: compter les valeurs uniques par catégorie

j'ai des données dans R qui ressemble à ceci:

 Cnty   Yr   Plt       Spp  DBH Ht Age
 1  185 1999 20001 Bitternut  8.0 54  47
 2  185 1999 20001 Bitternut  7.2 55  50
 3   31 1999 20001    Pignut  7.4 71  60
 4   31 1999 20001    Pignut 11.4 85 114
 5  189 1999 20001        WO 14.5 80  82
 6  189 1999 20001        WO 12.1 72  79

je voudrais savoir la quantité d'espèces uniques (Spp) dans chaque comté (Type). "unique (dfname$Spp)" me donne un nombre total d'espèces uniques dans la base de données, mais je voudrais qu'il par comté.

toute aide est appréciée! Désolé pour le formatage bizarre, c'est ma première question sur SO.

Merci.

10
demandé sur 42- 2013-04-23 05:10:22

7 réponses

j'ai essayé de rendre vos données d'échantillon un peu plus intéressantes. Actuellement, vos données d'échantillon n'ont qu'un seul "PSP" unique par "Cnty".

set.seed(1)
mydf <- data.frame(
  Cnty = rep(c("185", "31", "189"), times = c(5, 3, 2)),
  Yr = c(rep(c("1999", "2000"), times = c(3, 2)), 
         "1999", "1999", "2000", "2000", "2000"),
  Plt = "20001",
  Spp = sample(c("Bitternut", "Pignut", "WO"), 10, replace = TRUE),
  DBH = runif(10, 0, 15)
)
mydf
#    Cnty   Yr   Plt       Spp       DBH
# 1   185 1999 20001 Bitternut  3.089619
# 2   185 1999 20001    Pignut  2.648351
# 3   185 1999 20001    Pignut 10.305343
# 4   185 2000 20001        WO  5.761556
# 5   185 2000 20001 Bitternut 11.547621
# 6    31 1999 20001        WO  7.465489
# 7    31 1999 20001        WO 10.764278
# 8    31 2000 20001    Pignut 14.878591
# 9   189 2000 20001    Pignut  5.700528
# 10  189 2000 20001 Bitternut 11.661678

Ensuite, comme l'a suggéré, tapply est un bon candidat ici. Combiner unique et length pour obtenir les données que vous recherchez.

with(mydf, tapply(Spp, Cnty, FUN = function(x) length(unique(x))))
# 185 189  31 
#   3   2   2 
with(mydf, tapply(Spp, list(Cnty, Yr), FUN = function(x) length(unique(x))))
#     1999 2000
# 185    2    2
# 189   NA    2
# 31     1    1

si vous êtes intéressé par la tabulation simple (pas de valeurs uniques), alors vous pouvez explorer table et ftable:

with(mydf, table(Spp, Cnty))
#            Cnty
# Spp         185 189 31
#   Bitternut   2   1  0
#   Pignut      2   1  1
#   WO          1   0  2
ftable(mydf, row.vars="Spp", col.vars=c("Cnty", "Yr"))
#           Cnty  185       189        31     
#           Yr   1999 2000 1999 2000 1999 2000
# Spp                                         
# Bitternut         1    1    0    1    0    0
# Pignut            2    0    0    1    0    1
# WO                0    1    0    0    2    0
15
répondu A5C1D2H2I1M1N2O1R2T1 2013-04-23 04:01:29

comme Justin l'a mentionné, aggregate est probablement ce que vous voulez. Si vous appelez votre bloc de données foo, alors ce qui suit devrait vous donner ce que vous voulez, à savoir le nombre d'individus par espèce en supposant que chaque ligne avec Butternut représente un unique individu appartenant à l'espèce des espèces. Note: pour calculer la longueur du vecteur, c'est-à-dire le nombre d'individus (ligne) appartenant à chaque espèce, on a utilisé foo$HT ou foo $ DBH etc.

aggregate(foo$Age, by = foo[c('Spp','Cnty')], length)

santé,

Danny

2
répondu Arhopala 2013-04-23 01:40:28
with(mydf, tapply(Spp, list(Cnty, Yr), 
     FUN = function(x) length(unique(x))))

la requête unique ne fonctionne pas avec un grand ensemble de données je veux dire des données de plus de 1000K ligne.

0
répondu user3835068 2014-07-13 21:58:40

je voulais ajouter à ce Qu'un Handcart et Mohair ont mentionné. Pour ceux d'entre vous qui veulent obtenir les résultats du code ci-dessous dans une base de données(utile dans R studio)...

with(mydf, table(Spp, Cnty))
#            Cnty
# Spp         185 189 31
#   Bitternut   2   1  0
#   Pignut      2   1  1
#   WO          1   0  2
ftable(mydf, row.vars="Spp", col.vars=c("Cnty", "Yr"))
#           Cnty  185       189        31     
#           Yr   1999 2000 1999 2000 1999 2000
# Spp                                         
# Bitternut         1    1    0    1    0    0
# Pignut            2    0    0    1    0    1
# WO                0    1    0    0    2    0

Vous aurez besoin de mettre les sous.données.cadre.modificateur de matrice devant votre code comme suit:

as.data.frame.matrix(with(mydf, table(Spp, Cnty)))

j'étais assez nouveau à R quand je suis venu sur ce poste, et il m'a fallu beaucoup de temps pour comprendre cela, donc j'ai pensé que je partagerais.

0
répondu Matt Ober 2016-04-04 16:13:40

une solution simple utilisant le data.table approche.

library(data.table)

output <- setDT(mydf)[ , .(count=.N) , by = .(Spp,Cnty)]

dans le cas où vous voulez remodeler la sortie dans un beau format de tableau:

library(tidyr)

spread(data=a, key =Spp, count)

#   Cnty Bitternut Pignut WO
# 1:  185         2      2  1
# 2:  189         1      1 NA
# 3:   31        NA      1  2

# or perhaps like this:

spread(data=a, key =Cnty, count)

#          Spp 185 189 31
# 1: Bitternut   2   1 NA
# 2:    Pignut   2   1  1
# 3:        WO   1  NA  2
0
répondu rafa.pereira 2016-06-01 21:27:50

nous pouvons maintenant utiliser la fonction de comptage pour rendre cela plus facile.

tally(group_by(mydf, Spp, Cnty))

        Spp   Cnty     n
     <fctr> <fctr> <int>
1 Bitternut    185     2
2 Bitternut    189     1
3    Pignut    185     2
4    Pignut    189     1
5    Pignut     31     1
6        WO    185     1
7        WO     31     2
0
répondu Vaibhav Bhat 2017-04-04 17:15:34
set.seed(1)
mydf <- data.frame(
  Cnty = rep(c("185", "31", "189"), times = c(5, 3, 2)),
  Yr = c(rep(c("1999", "2000"), times = c(3, 2)), 
         "1999", "1999", "2000", "2000", "2000"),
  Plt = "20001",
  Spp = sample(c("Bitternut", "Pignut", "WO"), 10, replace = TRUE),
  DBH = runif(10, 0, 15)
)
mydf

dplyr::count() la fonction ressemble à une solution simple:

library(dplyr)
count(mydf, Spp, Cnty)
# A tibble: 7 x 3
# Spp       Cnty      n
# <fct>     <fct> <int>
# 1 Bitternut 185       2
# 2 Bitternut 189       1
# 3 Pignut    185       2
# 4 Pignut    189       1
# 5 Pignut    31        1
# 6 WO        185       1
# 7 WO        31        2
0
répondu Jot eN 2018-03-08 12:56:38