web-dev-qa-db-de.com

R: Zählen Sie eindeutige Werte nach Kategorie

Ich habe Daten in R, die folgendermaßen aussehen:

 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

Ich würde gerne die Menge der einzigartigen Arten (Spp) in jedem Bezirk (Cnty) wissen. "unique (dfname $ Spp)" gibt mir die Gesamtzahl der einzigartigen Arten im Datenrahmen an, aber ich möchte, dass es sich nach Landkreisen handelt.

Jede Hilfe wird geschätzt! Entschuldigung für die seltsame Formatierung. Dies ist meine erste Frage zu SO.

Vielen Dank.

10
Klaus Louis

Ich habe versucht, Ihre Beispieldaten etwas interessanter zu gestalten. Ihre Beispieldaten haben derzeit nur ein eindeutiges "Spp" pro "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

Wie vorgeschlagen, ist tapply hier ein guter Kandidat. Kombinieren Sie unique und length, um die Daten zu erhalten, nach denen Sie suchen.

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

Wenn Sie sich für einfache Tabellierung interessieren (nicht für eindeutige Werte), können Sie table und ftable erkunden:

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

Wie Justin erwähnt, ist das Aggregat wahrscheinlich das, was Sie wollen. Wenn Sie Ihren Datenrahmen als Foo bezeichnen, sollten Sie im Folgenden angeben, was Sie wollen, nämlich die Anzahl der Individuen pro Art, vorausgesetzt, dass jede Zeile mit Butternut eine eindeutige Person darstellt, die zu den Butternut-Arten gehört. Hinweis Ich habe foo $ Age verwendet, um die Länge des Vektors zu berechnen, d. H. Die Anzahl der Individuen (Reihe), die zu jeder Art gehören. Sie können jedoch foo $ Ht oder foo $ DBH usw. verwenden.

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

Prost,

Danny

2
Arhopala

Wir können jetzt die Tally-Funktion verwenden, um dies zu erleichtern.

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
Vaibhav Bhat
with(mydf, tapply(Spp, list(Cnty, Yr), 
     FUN = function(x) length(unique(x))))

eindeutige Abfrage funktioniert nicht mit großen Datenmengen Ich meine Daten mehr als 1000.000 Zeilen.

0
user3835068
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

Die Funktion dplyr::count() sieht wie eine einfache Lösung aus:

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
Jot eN

Ich wollte noch hinzufügen, was A Handcart And Mohair erwähnt hat. Für diejenigen von Ihnen, die die Ergebnisse des nachstehenden Codes in einen Datenrahmen bringen möchten (in R Studio hilfreich) ...

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

Sie müssen den Modifikator as.data.frame.matrix wie folgt vor Ihren Code setzen:

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

Als ich zu diesem Beitrag kam, war ich für R ziemlich neu. Ich habe lange gebraucht, um das herauszufinden, also dachte ich, ich würde es teilen.

0
Matt Ober

Eine einfache Lösung mit dem data.table-Ansatz.

library(data.table)

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

falls Sie die Ausgabe in ein besseres Tabellenformat umwandeln möchten:

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