2013-04-23 9 views
10

Ich habe Daten in R, die wie folgt aussieht:R: Zählen Sie eindeutige Werte nach Kategorie

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 möchte die Menge einzigartige Spezies (SPP) in jedem Bezirk (Cnty) kennen. "unique (dfname $ Spp)" gibt mir eine Gesamtanzahl von einzigartigen Arten im Datenrahmen, aber ich würde es nach Grafschaft mögen.

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

Danke.

+0

Willkommen SO. Teilen Sie mehr über Was Sie ausprobiert haben und wo Probleme auftreten, wird bessere Antworten liefern. Aber um Ihnen den Einstieg zu erleichtern, sind Funktionen wie "aggregate" und "tapply" hilfreich. Denken Sie daran, den Hilfetext einer Funktion mit '? aggregat' zu betrachten. – Justin

Antwort

2

Wie Justin erwähnte Aggregat ist wahrscheinlich, was Sie wollen. Wenn du deinen Datenrahmen foo nennst, dann sollte das Folgende geben, was du willst, nämlich die Anzahl der Individuen pro Spezies unter der Annahme, dass jede Reihe mit Butternut ein einzigartiges Individuum darstellt, das zur Butternussart gehört. Hinweis I $ foo Alter verwendet, um die Länge des Vektors, dh die Anzahl der Personen (Zeile) zu berechnen, zu jeder Art gehören, aber man konnte verwenden $ foo Ht oder foo $ DBH usw.

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

Cheers,

Danny

15

Ich habe versucht, Ihre Beispieldaten ein wenig interessanter zu machen. Ihre Beispieldaten haben derzeit nur einen eindeutigen "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 

nächstes wird, wie vorgeschlagen, ist tapply ein guter Kandidat hier. 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 in einfacher Auftabellierung (nicht eindeutigen Wertes) interessiert sind, dann können Sie erkunden table und 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 
+0

Ananda: Sehr gute Antwort! Sie haben richtigerweise angenommen, dass es mehr als eine Art von Arten pro Landkreis gibt, und genau das, was ich brauchte, zählt. Vielen Dank für Ihre Hilfe. –

+0

@KlausLouis, Freut mich zu hören. Wenn diese oder eine der anderen Antworten hilfreich waren, erwägen Sie, sie zu upbooten und/oder zu akzeptieren (http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) Sie. Danke und willkommen bei Stack Overflow! :) – A5C1D2H2I1M1N2O1R2T1

0
with(mydf, tapply(Spp, list(Cnty, Yr), 
    FUN = function(x) length(unique(x)))) 

einzigartige Abfrage wird mit großem Datensatz nicht funktioniert i Durchschnittsdaten mehr als 1000k Zeile.

0

Ich wollte hinzufügen, was A Handcart And Mohair erwähnt. Für die von Ihnen wollen, um die Ergebnisse des Code unten in einen Datenrahmen erhalten (hilfreich in 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 

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

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

war ich ziemlich neu in R, wenn ich auf diesen Beitrag kam, und es dauerte eine lange Zeit, um herauszufinden, so dass ich dachte, ich würde Aktie.

0

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

library(data.table) 

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

im Fall, dass Sie die Ausgabe in ein schöneres Tabellenformat neu zu gestalten:

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

Wir haben jetzt die Tally-Funktion verwenden können, 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
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 dplyr::count() Funktion sieht aus wie eine einfache Lösung:

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