Agregační funkce v jazyce R: summarize() a group_by() Příklad

⚡ Chytré shrnutí

Agregační funkce v R s dplyr sbalí mnoho řádků do jedné statistiky na skupinu. Tento návod spojí group_by() s summarize() na datech odpalování Lahmana pro výpočet průměrů, součtů, rozptylů, počtů a pozičních hodnot napříč 104 324 pozorováními.

  • 🧮 Jádrové sloveso: summarize(df, name = function(column)) vrací jeden řádek a group_by() ho nejprve převede na jeden řádek na skupinu.
  • 📊 Statistické rodiny: Průměr a medián popisují střed, standardní odchylka a mezikřížení odchylek popisují rozptyl, minimum a maximum popisují rozsah.
  • 🔢 Počítací: Funkce n() počítá řádky v aktuální skupině a funkce n_distinct() počítá jedinečné hodnoty v ní.
  • 📍 Poziční pomocníci: first(), last() a nth() např.trackonkrétní pozorování z každé skupiny.
  • 🔄 Práce s více sloupci: Funkce across() aplikuje jednu funkci na více sloupců, aniž by pro každý z nich opakovala kód.
  • 🔓 Grouping Hygiena: Před výpočtem, který musí být znovu spuštěn na celé tabulce, vždy volejte funkci ungroup().

Agregační funkce R

Datová sada použitá v tomto tutoriálu

Shrnutí proměnné vám poskytne první představu o datech a shrnutí podle skupin vám řekne mnohem více o tom, jak jsou hodnoty distribuovány. Tento tutoriál ukazuje, jak agregovat datovou sadu podle skupin pomocí knihovny dplyr.

Tento tutoriál používá Lahmanovu datovou sadu pro odpalování. Po jejím importu a uchováníping pouze devět níže uvedených sloupců, pracovní datový rámec obsahuje 104 324 pozorování a 9 proměnných:

  • playerID: ID hráče. Faktor
  • yearID: Rok. Faktor
  • teamID: Team. faktor
  • lgID: Liga. Faktor: AA AL FL NL PL UA
  • AB: U netopýrů. Numerický
  • G: Games: počet her hráčem. Numerický
  • R: Běží. Numerický
  • HR: Homeruny. Numerický
  • SH: Obětujte hity. Numerický

Než provedete shrnutí, provedete následující kroky k přípravě dat:

  • Krok 1: Importujte data
  • Krok 2: Vyberte příslušné proměnné
  • Krok 3: Seřaďte data
library(dplyr)

# Step 1
data <- read.csv("https://raw.githubusercontent.com/guru99-edu/R-Programming/master/lahman-batting.csv") %>%

# Step 2
select(c(playerID, yearID, AB, teamID, lgID, G, R, HR, SH))  %>% 

# Step 3
arrange(playerID, teamID, yearID)

Osvědčeným postupem při importu datové sady je použít funkci glimpse(), abyste získali představu o struktuře datové sady.

# Structure of the data
glimpse(data)

Výstup:

Observations: 104,324
Variables: 9
$ playerID <fctr> aardsda01, aardsda01, aardsda01, aardsda01, aardsda01, a...
$ yearID   <int> 2015, 2008, 2007, 2006, 2012, 2013, 2009, 2010, 2004, 196...
$ AB       <int> 1, 1, 0, 2, 0, 0, 0, 0, 0, 603, 600, 606, 547, 516, 495, ...
$ teamID   <fctr> ATL, BOS, CHA, CHN, NYA, NYN, SEA, SEA, SFN, ATL, ATL, A...
$ lgID     <fctr> NL, AL, AL, NL, AL, NL, AL, AL, NL, NL, NL, NL, NL, NL, ...
$ G        <int> 33, 47, 25, 45, 1, 43, 73, 53, 11, 158, 155, 160, 147, 15...
$ R        <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 113, 84, 100, 103, 95, 75...
$ HR       <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 39, 29, 44, 38, 47, 34, 40...
$ SH       <int> 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, ...

shrnout()

Syntaxe summarise() je základní a konzistentní s ostatními slovesy obsaženými v knihovně dplyr.

summarise(df, variable_name=condition) 
arguments: 
- `df`: Dataset used to construct the summary statistics 
- `variable_name=condition`: Formula to create the new variable

Podívejte se na kód níže:

summarise(data, mean_run =mean(R))

Code Vysvětlení

  • summarise(data, mean_run = mean(R)): Vytvoří proměnnou nazvanou mean_run, která je průměrem běhu sloupce z dat datové sady.

Výstup:

##   mean_run
## 1 19.20114

Můžete přidat tolik proměnných, kolik chcete. Vrátíte průměr odehraných her a průměrných obětí.

summarise(data, mean_games = mean(G),
    mean_SH = mean(SH, na.rm = TRUE))

Code Vysvětlení

  • mean_SH = mean(SH, na.rm = TRUE): Shrnutí druhé proměnné. Nastavili jste na.rm = TRUE, protože sloupec SH obsahuje chybějící pozorování.

Výstup:

##   mean_games  mean_SH
## 1   51.98361 2.340085

group_by() vs. Žádné group_by()

Použití funkce summarize() samostatně sbalí celý datový rámec do jednoho řádku, jak ukazují výše uvedené příklady. Její skutečná síla se projeví po přidání funkce group_by(): dplyr Knihovna poté aplikuje stejný výpočet samostatně na každou skupinu a vrací jeden řádek na skupinu.

Všimněte si, že group_by dokonale funguje se všemi ostatními slovesy (tj. mutate(), filter(), uspořádat(), …).

Je vhodné použít operátor potrubí, když máte více než jeden krok. Můžete vypočítat průměrný homerun podle baseballové ligy.

data %>%
	group_by(lgID) %>%
	summarise(mean_run = mean(HR))

Code Vysvětlení

  • data: Soubor dat používaný k vytvoření souhrnné statistiky
  • group_by(lgID): Rozdělí data podle hodnot lgID před sumarizací
  • summarise(mean_run = mean(HR)): Vypočítejte průměrný homerun

Výstup:

## 
# A tibble: 7 x 2
##     lgID  mean_run
##   <fctr>     <dbl>
## 1     AA 0.9166667
## 2     AL 3.1270988
## 3     FL 1.3131313
## 4     NL 2.8595953
## 5     PL 2.5789474
## 6     UA 0.6216216
## 7   <NA> 0.2867133	

Roupa funguje i s ggplot(), takže celý řetězec od nezpracovaných dat až po hotový graf zůstává v jednom příkazu. Následující kód kombinuje group_by(), summarize() a ggplot() a zobrazuje průměrný počet homerunů na ligu jako sloupcový graf.

Provedete následující krok:

  • Krok 1: Vyberte datový rámec
  • Krok 2: Seskupte data
  • Krok 3: Shrňte data
  • Krok 4: Vykreslete souhrnné statistiky
library(ggplot2)
# Step 1
data %>% 
#Step 2
group_by(lgID) %>% 
#Step 3
summarise(mean_home_run = mean(HR)) %>% 
#Step 4
ggplot(aes(x = lgID, y = mean_home_run, fill = lgID)) +
    geom_bar(stat = "identity") +
    theme_classic() +
    labs(
        x = "baseball league",
        y = "Average home run",
        title = paste(
            "Example group_by() with summarise()"
        )
    )

Výstup:

Seskupit podle příkladu pomocí Sumarizovat

Funkce, které můžete použít uvnitř summarize()

Sloveso summarise() je kompatibilní s téměř všemi funkcemi v R. Zde je krátký seznam užitečných funkcí, které můžete použít společně s summarise():

Objektivní funkce Description
Basic znamenat() Průměr vektoru x
medián() Medián vektoru x
součet() Součet vektoru x
změna sd() směrodatná odchylka vektoru x
IQR() Mezikvartil vektoru x
Rozsah min() Minimum vektoru x
max() Maximum vektoru x
kvantil() Kvantil vektoru x
Pozice První() Použijte s group_by() První pozorování skupiny
poslední() Použijte s group_by(). Poslední pozorování skupiny
n-tý() Použijte s group_by(). n-té pozorování skupiny
Počítat n () Použijte s group_by(). Spočítejte počet řádků
n_distinct() Použijte s group_by(). Spočítejte počet různých pozorování

Níže uvedené části popisují příklad pro každou funkci uvedenou v tabulce výše. Pokud s roure a dalšími slovesy teprve začínáte, začněte s Výukový program pro výběr, filtrování a uspořádání.

Základní funkce

V předchozím příkladu jste neuložili souhrnnou statistiku do datového rámce.

Datový rámec můžete ze souhrnu vygenerovat ve dvou krocích:

  • Krok 1: Uložte datový rámec pro další použití
  • Krok 2: Použijte datovou sadu k vytvoření čárového grafu

Krok 1) Vypočítáte průměrný počet odehraných her za rok.

## Mean
ex1 <- data %>%
	group_by(yearID) %>%
	summarise(mean_game_year = mean(G))
head(ex1)

Code Vysvětlení

  • Souhrnná statistika datové sady pálkování je uložena v datovém rámci ex1.

Výstup:

## # A tibble: 6 x 2
##   yearID mean_game_year
##    <int>          <dbl>
## 1   1871       23.42308
## 2   1872       18.37931
## 3   1873       25.61538
## 4   1874       39.05263
## 5   1875       28.39535
## 6   1876       35.90625	

Krok 2) Souhrnnou statistiku zobrazíte pomocí čárového grafu a uvidíte trend.

# Plot the graph
ggplot(ex1, aes(x = yearID, y = mean_game_year)) +
    geom_line() +
    theme_classic() +
    labs(
        x = "Year",
        y = "Average games played",
        title = paste(
            "Average games played from 1871 to 2016"
        )
    )

Výstup:

Příklad základní funkce

Podmnožina

Funkce summarise() je kompatibilní s podmnožinou.

## Subsetting + Median
data %>%
group_by(lgID) %>%
summarise(median_at_bat_league = median(AB), 
	#Compute the median without the zero 
	median_at_bat_league_no_zero = median(AB[AB > 0]))

Code Vysvětlení

  • median_at_bat_league_no_zero = medián(AB[AB > 0]): Proměnná AB obsahuje mnoho 0. Můžete porovnat medián u netopýra proměnná s a bez 0.

Výstup:

## # A tibble: 7 x 3
##     lgID median_at_bat_league median_at_bat_league_no_zero
##   <fctr>                <dbl>                        <dbl>
## 1     AA                  130                          131
## 2     AL                   38                           85
## 3     FL                   88                           97
## 4     NL                   56                           67
## 5     PL                  238                          238
## 6     UA                   35                           35
## 7   <NA>                  101                          101	

Součet

Další užitečnou funkcí pro agregaci proměnné je sum().

Můžete zkontrolovat, které ligy mají více homerunů.

## Sum
data %>%
	group_by(lgID) %>%
	summarise(sum_homerun_league = sum(HR))

Výstup:

## # A tibble: 7 x 2
##     lgID sum_homerun_league
##   <fctr>              <int>
## 1     AA                341
## 2     AL              29426
## 3     FL                130
## 4     NL              29817
## 5     PL                 98
## 6     UA                 46
## 7   <NA>                 41	

Směrodatná odchylka

Rozložení v datech se vypočítá se směrodatnou odchylkou nebo sd() v R.

# Spread
data %>%
	group_by(teamID) %>%
	summarise(sd_at_bat_league = sd(HR))

Výstup:

## # A tibble: 148 x 2
##    teamID sd_at_bat_league
##    <fctr>            <dbl>
##  1    ALT               NA
##  2    ANA        8.7816395
##  3    ARI        6.0765503
##  4    ATL        8.5363863
##  5    BAL        7.7350173
##  6    BFN        1.3645163
##  7    BFP        0.4472136
##  8    BL1        0.6992059
##  9    BL2        1.7106757
## 10    BL3        1.0000000
## # ... with 138 more rows		

Rozpětí v homerunech se mezi týmy značně liší a ALT vrací NA, protože daný tým má pouze jeden řádek, takže nelze vypočítat směrodatnou odchylku.

Minimum a maximum

K minimu a maximu vektoru můžete přistupovat pomocí funkce min() a max().

Níže uvedený kód vrací nejnižší a nejvyšší počet her v sezóně, kterou hráč hraje.

# Min and max
data %>%
	group_by(playerID) %>%
	summarise(min_G = min(G),
    max_G = max(G))

Výstup:

## # A tibble: 10,395 x 3
##     playerID min_G max_G
##       <fctr>       <int>
##  1 aardsda01    53    73
##  2 aaronha01   120   156
##  3  aasedo01    24    66
##  4  abadfe01    18    18
##  5 abadijo01    11    11
##  6 abbated01     3   153
##  7 abbeybe01    11    11
##  8 abbeych01    80   132
##  9 abbotgl01     5    23
## 10 abbotji01    13    29
## # ... with 10,385 more rows

Počítat

Počítání pozorování na skupinu se vždy vyplatí. V R vrací n() počet řádků v aktuální skupině.

Například níže uvedený kód vypočítá počet let odehraných každým hráčem.

# count observations
data %>%
	group_by(playerID) %>%
	summarise(number_year = n()) %>%
	arrange(desc(number_year))

Výstup:

## # A tibble: 10,395 x 2
##     playerID number_year
##       <fctr>       <int>
##  1 pennohe01          11
##  2 joosted01          10
##  3 mcguide01          10
##  4  rosepe01          10
##  5 davisha01           9
##  6 johnssi01           9
##  7  kaatji01           9
##  8 keelewi01           9
##  9 marshmi01           9
## 10 quirkja01           9
## # ... with 10,385 more rows

První a poslední

Můžete vybrat první, poslední nebo n-tou pozici skupiny.

Můžete například najít první a poslední rok každého hráče.

# first and last
data %>%
	group_by(playerID) %>%
	summarise(first_appearance = first(yearID),
		last_appearance = last(yearID))

Výstup:

## # A tibble: 10,395 x 3
##     playerID first_appearance last_appearance
##       <fctr>            <int>           <int>
##  1 aardsda01             2009            2010
##  2 aaronha01             1973            1975
##  3  aasedo01             1986            1990
##  4  abadfe01             2016            2016
##  5 abadijo01             1875            1875
##  6 abbated01             1905            1897
##  7 abbeybe01             1894            1894
##  8 abbeych01             1895            1897
##  9 abbotgl01             1973            1979
## 10 abbotji01             1992            1996
## # ... with 10,385 more rows

n-té pozorování

Funkce nth() doplňuje funkce first() a last(). Vrací pozorování na indexu, který předáte v rámci každé skupiny.

Můžete například filtrovat pouze druhý rok, kdy tým hrál.

# nth
data %>%
	group_by(teamID) %>%
	summarise(second_game = nth(yearID, 2)) %>%
	arrange(second_game)

Výstup:

## # A tibble: 148 x 2
##    teamID second_game
##    <fctr>       <int>
##  1    BS1        1871
##  2    CH1        1871
##  3    FW1        1871
##  4    NY2        1871
##  5    RC1        1871
##  6    BR1        1872
##  7    BR2        1872
##  8    CL1        1872
##  9    MID        1872
## 10    TRO        1872
## # ... with 138 more rows

Různý počet pozorování

Funkce n() vrací počet řádků v aktuální skupině. Související funkce n_distinct() místo toho počítá jedinečné hodnoty.

V dalším příkladu sečtete celkový počet hráčů, které tým naverboval během všech období.

# distinct values
data %>%
	group_by(teamID) %>%
	summarise(number_player = n_distinct(playerID)) %>%
	arrange(desc(number_player))

Code Vysvětlení

  • group_by(teamID): Seskupit podle týmu
  • summarise(číslo_hráče = n_výrazný(ID hráče)): Spočítejte jednotlivé hráče v každém týmu
  • aranž (desc(číslo_hráče)): Seřaďte data podle počtu hráčů

Výstup:

## # A tibble: 148 x 2
##    teamID number_player
##    <fctr>         <int>
##  1    CHN           751
##  2    SLN           729
##  3    PHI           699
##  4    PIT           683
##  5    CIN           679
##  6    BOS           647
##  7    CLE           646
##  8    CHA           636
##  9    DET           623
## 10    NYA           612
## # ... with 138 more rows

Více skupin

Souhrnnou statistiku lze realizovat mezi více skupinami.

# Multiple groups
data %>%
	group_by(yearID, teamID) %>%
	summarise(mean_games = mean(G)) %>%
	arrange(desc(teamID, yearID))

Code Vysvětlení

  • group_by(yearID, teamID): Seskupit podle roku a tým
  • summarize(mean_games = mean(G)): Průměrný počet odehraných her
  • uspořádat(desc(teamID, yearID)): Seřadit data podle týmu a roku

Výstup:

## # A tibble: 2,829 x 3
## # Groups:   yearID [146]
##    yearID teamID mean_games
##     <int> <fctr>      <dbl>
##  1   1884    WSU   20.41667
##  2   1891    WS9   46.33333
##  3   1886    WS8   22.00000
##  4   1887    WS8   51.00000
##  5   1888    WS8   27.00000
##  6   1889    WS8   52.42857
##  7   1884    WS7    8.00000
##  8   1875    WS6   14.80000
##  9   1873    WS5   16.62500
## 10   1872    WS4    4.20000
## # ... with 2,819 more rows

Filtr

Než zamýšlíte provést operaci, můžete datovou sadu filtrovat. Soubor dat začíná v roce 1871 a analýza nepotřebuje roky před rokem 1980.

# Filter
data %>%
	filter(yearID > 1980) %>%
	group_by(yearID) %>%
	summarise(mean_game_year = mean(G))

Code Vysvětlení

  • filter(yearID > 1980): Filtrujte data tak, aby zobrazovaly pouze relevantní roky (tj. po roce 1980)
  • group_by(yearID): Seskupit podle roku
  • summarise(mean_game_year = mean(G)): Shrnutí dat

Výstup:

## # A tibble: 36 x 2
##    yearID mean_game_year
##     <int>          <dbl>
##  1   1981       40.64583
##  2   1982       56.97790
##  3   1983       60.25128
##  4   1984       62.97436
##  5   1985       57.82828
##  6   1986       58.55340
##  7   1987       48.74752
##  8   1988       52.57282
##  9   1989       58.16425
## 10   1990       52.91556
## # ... with 26 more rows

Oddělit

Nakonec musíte odstranit groovping před změnou úrovně, na které výpočet probíhá. Bez funkce ungroup() by druhá funkce summarize() stále fungovala pro každého hráče.

# Ungroup the data
data %>%
	filter(HR > 0) %>%
	group_by(playerID) %>%
	summarise(average_HR_game = sum(HR) / sum(G)) %>%
	ungroup() %>%
	summarise(total_average_homerun = mean(average_HR_game))

Code Vysvětlení

  • filtr(HR >0) : Vyloučí nulový homerun
  • group_by(playerID): skupina po hráči
  • summarise(average_HR_game = sum(HR)/sum(G)): Vypočítejte průměrný homerun hráčem
  • ungroup(): odstraní skupinuping
  • summarise(total_average_homerun = mean(average_HR_game)): Shrnutí dat

Výstup:

## # A tibble: 1 x 1
##   total_average_homerun
##                   <dbl>
## 1            0.06882226	

Jak shrnout více sloupců pomocí across()

Každý výše uvedený příklad pojmenovává jeden sloupec najednou. Pokud je stejná statistika potřeba pro více sloupců, metoda across() ji použije na všechny v jednom volání.

# One function, several columns
data %>%
    group_by(lgID) %>%
    summarise(across(c(R, HR, G), mean, .names = "mean_{.col}"))

# Every numeric column at once
data %>%
    group_by(lgID) %>%
    summarise(across(where(is.numeric), mean, na.rm = TRUE))

# Several functions applied to several columns
data %>%
    group_by(teamID) %>%
    summarise(across(c(R, HR), list(avg = mean, total = sum)))

Chování řídí tři argumenty:

  • .cols: sloupce, se kterými se má pracovat, zapsané se stejnými pomocníky jako select(), včetně where(is.numeric).
  • .fnsjedna funkce nebo pojmenovaný seznam funkcí, které se mají použít pro každý sloupec.
  • .jména: vzor pojmenování výstupu, kde {.col} je sloupec a {.fn} název funkce.

Funkce across() nahradila starší pomocné funkce summarize_all(), summarize_at() a summarize_if() v dplyr 1.0.0. Ty stále běží, ale jsou nahrazeny, takže nový kód by měl používat across().

Časté chyby funkce summarize() a jak je opravit

Čtyři problémy jsou zodpovědné za většinu neúspěšných agregací.

  • Výsledkem je nulový počet bodů. Funkce mean() a sum() vrátí NA, pokud nějaká hodnota chybí. Přidejte na.rm = TRUE, jak to dělá výše uvedený příklad mean_SH.
  • Zpráva „summarise() seskupil výstup“. Grouping dvěma proměnnými ponechá výsledek seskupený podle první z nich. Pro odstranění skupiny použijte parametr .groups = „drop“.ping, nebo následně zavolejte ungroup().
  • Pozdější výpočet udává nesprávnou úroveň. Datový rámec zůstává seskupený, dokud jej nerozskupíte, takže pro každou skupinu se stále spustí druhá funkce summarize(). Přesně to demonstruje příklad s funkcí ungroup().
  • Výstup má více řádků, než se očekávalo. summarize() vrací jeden řádek na skupinu, takže se jedná o nezamýšlenou skupinuping proměnná vynásobí výstup. Zkontrolujte řádek „Skupiny:“ vytištěný nad libovolným tibble.
# Drop the grouping as part of the call
data %>%
    group_by(yearID, teamID) %>%
    summarise(mean_games = mean(G), .groups = "drop")

summarize() v R: Referenční příručka k funkci

Chcete-li vrátit souhrn podle skupin, nejprve rozdělte data:

# group by X1, X2, X3
group_by(df, X1, X2, X3)

a odstraňte groovyping když se úroveň výpočtu změní:

ungroup(df)

V následující tabulce jsou uvedeny všechny funkce použité s funkcí summarize() v tomto tutoriálu:

Metoda funkce Code
střední střední
summarise(df, mean_x1 = mean(x1))
medián medián
summarise(df, median_x1 = median(x1))
součet součet
summarise(df, sum_x1 = sum(x1))
standardní odchylka sd
summarise(df, sd_x1 = sd(x1))
mezikvartilní IQR
summarise(df, interquartile_x1 = IQR(x1))
minimálně min
summarise(df, minimum_x1 = min(x1))
maximum max
summarise(df, maximum_x1 = max(x1))
kvantil kvantil
summarise(df, quantile_x1 = quantile(x1, probs = 0.75))
první pozorování První
summarise(df, first_x1 = first(x1))
poslední pozorování poslední
summarise(df, last_x1 = last(x1))
n-té pozorování n
summarise(df, nth_x1 = nth(x1, 2))
počet výskytů n
summarise(df, n_x1 = n())
počet zřetelných výskytů n_výrazný
summarise(df, n_distinct_x1 = n_distinct(x1))

Nejčastější dotazy

Funkce summarize() sbalí každou skupinu do jednoho řádku statistik. Funkce mutate() zachová každý řádek a přidá nový sloupec. Funkce mutate() se používá, když se skupinová statistika musí nacházet vedle původních pozorování.

Grouping Použití dvou nebo více proměnných ponechá výsledek seskupený podle všech proměnných kromě poslední. Funkce dplyr vás varuje, protože pozdější slovesa by se tiše spouštěla ​​pro každou skupinu. Abyste se tomu vyhnuli, použijte .groups = „drop“.

Funkce n() počítá všechny řádky v aktuální skupině, včetně opakování. Funkce n_distinct() počítá jedinečné hodnoty ve sloupci. Počítání hráčů v týmu vyžaduje funkci n_distinct(), protože jeden hráč se objeví v mnoha sezónách.

Agregáty na úrovni skupin, jako jsou průměry zákazníků, počty a hodnoty aktuálnosti, patří mezi nejsilnější prediktory v tabulkových modelech umělé inteligence. group_by() s summarize() je standardní způsob, jak je reprodukovatelně sestavit.

Ano. Asistenti s umělou inteligencí mohou přepsat aggregate() a tapply() jako pipeline group_by() a summarize(). Porovnejte počty řádků v obou verzích, protože základní R a dplyr zpracovávají chybějící skupiny odlišně.

Shrňte tento příspěvek takto: