2013-04-23 34 views
10

mam danych w R, który wygląda tak:R: liczba unikalnych wartości według kategorii

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 

chciałbym znać ilość unikalnych gatunków (SPP) w każdym okręgu (Cnty). "unique (dfname $ Spp)" daje mi całkowitą liczbę unikatowych gatunków w ramce danych, ale chciałbym to zrobić w hrabstwie.

Każda pomoc jest doceniana! Przepraszamy za dziwne formatowanie, jest to moje pierwsze pytanie na temat SO.

Dzięki.

+0

Witamy w SO. Udostępnianie informacji o tym, co próbujesz i gdzie masz problemy, da lepsze odpowiedzi. Ale, aby zacząć, pomocne są funkcje takie jak 'aggregate' i' tapply'. pamiętaj, aby spojrzeć na tekst pomocy z funkcji używającej '? aggregate'. – Justin

Odpowiedz

2

Jak wspomniał Justin, agregat jest prawdopodobnie tym, czego potrzebujesz. Jeśli nazwiesz swoją ramkę danych foo, to poniższe powinny dać ci to, czego chcesz, czyli liczbę osobników na gatunek, zakładając, że każdy wiersz z Butternut reprezentuje unikalną osobowość należącą do gatunku butternut. Uwaga użyłem $ foo Wiek obliczyć długość wektora, czyli liczby osób (wiersz), należące do danego gatunku, ale można użyć $ foo Ht lub foo $ dbh itp

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

Cheers,

Danny

15

Starałem się, aby twoje dane przykładowe były trochę bardziej interesujące. Twoje przykładowe dane mają obecnie tylko jeden unikalny "Spp" na "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 

Następnie, jak sugerowano, tapply jest dobrym kandydatem tutaj. Połącz unique i length, aby uzyskać dane, których szukasz.

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 

Jeśli jesteś zainteresowany prostą zestawianiu (nie unikalnych wartości), a następnie można zbadać table i 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: Bardzo dobra odpowiedź! Prawidłowo założyłeś, że istnieje więcej niż jeden rodzaj gatunków na okręg, a dokładnie to, czego potrzebowałem, to liczba. Bardzo ci dziękuje za pomoc. –

+0

@KlausLouis, Miło mi to słyszeć. Jeśli ta lub jakakolwiek inna odpowiedź była pomocna, rozważ rozważenie ich i/lub zaakceptowanie (http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) jednego z im. Dzięki i witamy w Stack Overflow! :) – A5C1D2H2I1M1N2O1R2T1

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

wyjątkowy zapytanie nie pracuje z dużego zestawu danych i średnie dane ponad 1000 tys. wierszy.

0

Chciałem dodać do tego, o czym wspomniał wózek ręczny i moher. Dla tych z Was, którzy chcą uzyskać wyniki poniżej kod do ramki danych (pomocne w studio R) ...

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 

Musisz umieścić modyfikator as.data.frame.matrix przed od kodu tak:

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

jestem całkiem nowy, R, gdy natknąłem się na to stanowisko, i zajęło mi dużo czasu, aby zrozumieć, że obecnie, więc pomyślałem, że podzielę.

0

Proste rozwiązanie przy użyciu podejścia data.table.

library(data.table) 

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

w przypadku, gdy chcesz zmienić kształt wyjście do ładniejszy formacie tabeli:

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

Możemy teraz wykorzystać funkcję sygnalizacyjną, aby to ułatwić.

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 

Funkcja dplyr::count() wygląda proste rozwiązanie:

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