Względne częstotliwości / proporcje z dplyr

Załóżmy, że chcę obliczyć proporcję różnych wartości w każdej grupie. Na przykład, korzystając z danych mtcars, Jak obliczyć względną częstotliwość liczby biegów przez am (automatyczny/ręczny) za jednym razem z dplyr?

library(dplyr)
data(mtcars)
mtcars <- tbl_df(mtcars)

# count frequency
mtcars %>%
  group_by(am, gear) %>%
  summarise(n = n())

# am gear  n
#  0    3 15 
#  0    4  4 
#  1    4  8  
#  1    5  5 

Co chciałbym osiągnąć:

am gear  n rel.freq
 0    3 15      0.7894737
 0    4  4      0.2105263
 1    4  8      0.6153846
 1    5  5      0.3846154
Author: jenswirf, 2014-07-04

5 answers

Spróbuj tego:

mtcars %>%
  group_by(am, gear) %>%
  summarise (n = n()) %>%
  mutate(freq = n / sum(n))

#   am gear  n      freq
# 1  0    3 15 0.7894737
# 2  0    4  4 0.2105263
# 3  1    4  8 0.6153846
# 4  1    5  5 0.3846154

Z winieta dplyr:

Gdy grupujesz według wielu zmiennych, każde podsumowanie usuwa jeden poziom grupowania. Ułatwia to stopniowe zwijanie zestawu danych.

Tak więc, po summarise, zmienna grupująca "gear" jest odrywana, a dane są następnie grupowane "tylko" przez " am " (wystarczy sprawdzić to za pomocą groups Na danych wynikowych), na których następnie wykonujemy obliczenia mutate.

Wynik "peeling" jest oczywiście zależny od kolejności grupowania zmiennych w wywołaniu group_by. Tym razem mieliśmy szczęście, że oddzieliła ona żądaną zmienną. Możesz chcieć wykonać kolejną group_by(am), aby uczynić kod bardziej wyraźnym.

Dla zaokrąglenia i prettyfikacji, proszę odnieść się do ładnej odpowiedzi autorstwa @ Tyler Rinker.

 182
Author: Henrik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-28 17:35:42

Można użyć funkcji count(), która ma jednak inne zachowanie w zależności od wersji dplyr:

  • Dplyr 0.7.1: zwraca tabelę rozgrupowaną {[13] }: należy ponownie grupować według am

  • Dplyr zgrupowaną tabelę, więc nie trzeba ponownie grupować, chociaż możesz chcieć ungroup() dla późniejszych manipulacji

Dplyr 0.7.1

mtcars %>%
  count(am, gear) %>%
  group_by(am) %>%
  mutate(freq = n / sum(n))

Dplyr

mtcars %>%
  count(am, gear) %>%
  mutate(freq = n / sum(n))

To wyniki w tabeli grouped , jeśli chcesz użyć jej do dalszej analizy, przydatne może być usunięcie atrybutu grouped z ungroup().

 25
Author: Matifou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-19 21:49:42

@ Henrik ' s jest lepsze dla użyteczności, ponieważ spowoduje to, że kolumna będzie znakowana i nie będzie już numeryczna, ale pasuje do tego, o co prosiłeś...

mtcars %>%
  group_by (am, gear) %>%
  summarise (n=n()) %>%
  mutate(rel.freq = paste0(round(100 * n/sum(n), 0), "%"))

##   am gear  n rel.freq
## 1  0    3 15      79%
## 2  0    4  4      21%
## 3  1    4  8      62%
## 4  1    5  5      38%

EDIT Bo Spacedman o to prosił: -)

as.rel_freq <- function(x, rel_freq_col = "rel.freq", ...) {
    class(x) <- c("rel_freq", class(x))
    attributes(x)[["rel_freq_col"]] <- rel_freq_col
    x
}

print.rel_freq <- function(x, ...) {
    freq_col <- attributes(x)[["rel_freq_col"]]
    x[[freq_col]] <- paste0(round(100 * x[[freq_col]], 0), "%")   
    class(x) <- class(x)[!class(x)%in% "rel_freq"]
    print(x)
}

mtcars %>%
  group_by (am, gear) %>%
  summarise (n=n()) %>%
  mutate(rel.freq = n/sum(n)) %>%
  as.rel_freq()

## Source: local data frame [4 x 4]
## Groups: am
## 
##   am gear  n rel.freq
## 1  0    3 15      79%
## 2  0    4  4      21%
## 3  1    4  8      62%
## 4  1    5  5      38%
 20
Author: Tyler Rinker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-04 18:35:57

Oto ogólna funkcja implementująca rozwiązanie Henrika na dplyr 0.7.1.

freq_table <- function(x, 
                       group_var, 
                       prop_var) {
  group_var <- enquo(group_var)
  prop_var  <- enquo(prop_var)
  x %>% 
    group_by(!!group_var, !!prop_var) %>% 
    summarise(n = n()) %>% 
    mutate(freq = n /sum(n)) %>% 
    ungroup
}
 3
Author: Edwin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-19 14:18:36

Ta odpowiedź jest oparta na odpowiedzi Matifou.

Najpierw zmodyfikowałem go, aby upewnić się, że kolumna freq nie zostanie zwrócona jako kolumna notacji naukowej za pomocą opcji scipen.

Następnie mnożę odpowiedź przez 100, aby uzyskać procent, a nie dziesiętny, aby kolumna freq była łatwiejsza do odczytania jako procent.

getOption("scipen") 
options("scipen"=10) 
mtcars %>%
count(am, gear) %>% 
mutate(freq = (n / sum(n)) * 100)
 1
Author: Jazzmine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-22 11:28:43