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