Tutoriál k dplyr v R: Sloučení a spojení dat s příklady

⚡ Chytré shrnutí

Balíček dplyr v jazyce R slučuje a spojuje datové rámce pomocí čtyř sloves: left_join(), right_join(), inner_join() a full_join(). Jeho doprovodný balíček tidyr poté přetváří spojený výsledek pomocí gather(), spread(), separate() a unite().

  • 🔗 Mutující spojení: Funkce left_join() uchovává každý řádek původní tabulky a funkce right_join() uchovává každý řádek cílové tabulky.
  • 🎯 Kontrola zápasu: inner_join() zahodí neshodné řádky, zatímco full_join() si ponechá obě strany a mezery vyplní hodnotou NA.
  • 🗝️ Kompozitní klíče: Předejte = c(“ID”, “year”) vždy, když jeden sloupec jednoznačně neidentifikuje řádek.
  • 🔄 Rešaping: gather() otočí širokou tabulku na délku a spread() ji otočí zpět, keeping jedna proměnná na sloupec.
  • ✂️ Rozdělení a sjednocení: separate() rozděluje sloupec podle oddělovače a unite() zřetězuje sloupce zpět do jednoho.
  • ⚠️ Poznámka k verzi: pivot_longer(), pivot_wider() a separate_wider_delim() nahrazují starší resha v tidyr.ping funkce.

Dplyr v R: Sloučení a spojení dat

Úvod do analýzy dat

Před jakýmkoli připojením nebo změnouping sloveso dává smysl, pomáhá vidět, kam se hodí manipulace s daty. Analýza dat lze rozdělit do tří částí:

  • Extracvání: Nejprve musíme shromáždit data z mnoha zdrojů a zkombinovat je.
  • Změnit: Tento krok zahrnuje manipulaci s daty. Jakmile zkonsolidujeme všechny zdroje dat, můžeme začít data čistit.
  • Vizualizujte: Posledním krokem je vizualizace našich dat pro kontrolu nesrovnalostí.

Níže uvedený diagram ukazuje, jak jsou tyto tři fáze propojeny.

Třístupňový proces analýzy dat ukazující extracce, transformace a vizualizace
Proces analýzy dat

Jednou z nejvýznamnějších výzev, kterým datoví vědci čelí, je manipulace s daty. Data nikdy nejsou k dispozici v požadovaném formátu. Datoví vědci musí strávit alespoň polovinu svého času čištěním a manipulací s daty. To je jeden z nejdůležitějších úkolů v jejich práci. Pokud proces manipulace s daty není úplný, přesný a důsledný, model nebude fungovat správně.

R dplyr

Jazyk R má balíček s názvem dplyr, který se stará o transformaci dat. Je postaven na malé sadě základních sloves – filter(), select(), arrange(), mutate() a summarize() – a na rodině funkcí join. Jakmile jsou data upravena, ggplot2 je dokáže vizualizovat.

Naučíme se, jak používat balíček dplyr k manipulaci s Datový rámecPokud R ještě není nainstalováno, postupujte podle Kroky nastavení R a RStudioa poté spusťte install.packages(„dplyr“).

Sloučení dat s dplyr

dplyr poskytuje pěkný a pohodlný způsob, jak kombinovat datové sady. Můžeme mít mnoho zdrojů vstupních dat a v určitém okamžiku je musíme zkombinovat. Spojení s dplyr přidá proměnné napravo od původní datové sady.

dplyr se připojuje

Následují čtyři důležité typy spojení používané v dplyr ke sloučení dvou datových sad. Všechny čtyři přijímají stejné argumenty – dvě tabulky a klíč – a liší se pouze v tom, které neshodné řádky přežijí:

funkce Objektivní Argumenty Více kláves
left_join() Sloučit dvě datové sady. Uchovávejte všechna pozorování z tabulky původu x, y, by = „ID“ x, y, by = c(„ID“, „ID2“)
right_join() Sloučit dvě datové sady. Uchovávejte všechna pozorování z cílové tabulky x, y, by = „ID“ x, y, by = c(„ID“, „ID2“)
vnitřní spojení() Sloučit dvě datové sady. Vyloučit všechny neshodné řádky. x, y, by = „ID“ x, y, by = c(„ID“, „ID2“)
full_join() Sloučit dva soubory dat. Zachovat všechna pozorování. x, y, by = „ID“ x, y, by = c(„ID“, „ID2“)

Tato čtyři slovesa se mapují na spojení LEFT, RIGHT, INNER a FULL OUTER SQLZákladní R dosahuje stejných výsledků pomocí argumentů all, all.x a all.y funkce. spojit().

Všechny typy spojení si prostudujeme na jednoduchém příkladu.

Nejprve si vytvoříme dva datové soubory. Tabulka 1 obsahuje dvě proměnné, ID a y, zatímco tabulka 2 shromažďuje ID a z. V každé situaci potřebujeme mít klíčový pár variabilní. V našem případě je ID naše klíč proměnná. Funkce bude hledat shodné hodnoty v obou tabulkách a vracející se hodnoty naváže napravo od tabulky 1. Obrázek níže ukazuje obě tabulky vedle sebe.

Dvě ukázkové tabulky sdílející klíčový sloupec ID před sloučením dplyr

library(dplyr)
df_primary <- tribble(
  ~ID, ~y,
   "A", 5,
   "B", 5,
   "C", 8,
   "D", 0,
  "F", 9)
df_secondary <- tribble(
  ~ID, ~z,
   "A", 30,
   "B", 21,
   "C", 22,
   "D", 25,
   "E", 29)

dplyr left_join()

Nejběžnějším způsobem sloučení dvou datových sad je použití funkce left_join(). Obrázek níže ukazuje, že pár klíčů odpovídá řádkům A, B, C a D, zatímco E a F zůstávají. Pomocí funkce left_join() ponecháme všechny řádky v původní tabulce a ignorujeme řádky, které v cílové tabulce nemají žádný pár klíčů. V našem příkladu hodnota E v tabulce 1 neexistuje, takže tento řádek je odstraněn. Hodnota F pochází z původní tabulky, takže je ponechána za funkcí left_join() a vrací NA ve sloupci z.

Příklad dplyr left_join()

Níže uvedený diagram znázorňuje, co se děje během funkce left_join().

Schéma dplyr left_join keeping každý řádek původní tabulky a odstraňteping ID E

left_join(df_primary, df_secondary, by ='ID')

Výstup:

## 
# A tibble: 5 x 3
##      ID   y.x   y.y
##   <chr> <dbl> <dbl>		
## 1     A     5    30
## 2     B     5    21
## 3     C     8    22
## 4     D     0    25
## 5     F     9    NA

Všimněte si, že pokud obě tabulky obsahují sloupec se stejným názvem, funkce dplyr je odliší pomocí přípon .x a .y uvedených výše.

dplyr right_join()

Funkce right_join() funguje úplně stejně jako left_join(). Jediný rozdíl je vynechaný řádek. Hodnota E dostupná v cílovém datovém rámci existuje v nové tabulce a má hodnotu NA pro sloupec y.

Příklad dplyr right_join()

Níže uvedený diagram znázorňuje zrcadlový obraz.

Schéma příkazu dplyr right_join keeping každý řádek cílové tabulky a odstraňteping ID F

right_join(df_primary, df_secondary, by = 'ID')

Výstup:

##
# A tibble: 5 x 3
##      ID   y.x   y.y
##   <chr> <dbl> <dbl>
## 1     A     5    30
## 2     B     5    21
## 3     C     8    22
## 4     D     0    25
## 5     E    NA    29

dplyr inner_join()

Když neporovnaná pozorování nejsou vůbec užitečná, můžeme se vrátit 👔 řádky, které existují v oba datové sady. Toto je správná volba, když potřebujeme kompletní datovou sadu a nechceme chybějící hodnoty imputovat pomocí průměru nebo mediánu.

Zde nám pomůže funkce inner_join(). Vyloučí neshodné řádky na obou stranách.

Příklad dplyr inner_join()

Níže uvedený diagram znázorňuje čtyři ID, která přežijí spojení.

Schéma dplyr inner_join vracející pouze čtyři ID přítomná v obou tabulkách

inner_join(df_primary, df_secondary, by ='ID')

Výstup:

## 
# A tibble: 4 x 3
##      ID   y.x   y.y
##   <chr> <dbl> <dbl>
## 1     A     5    30
## 2     B     5    21
## 3     C     8    22
## 4     D     0    25

dplyr full_join()

Nakonec funkce full_join() uchová všechna pozorování a chybějící hodnoty nahradí hodnotou NA.

Příklad dplyr full_join()

Níže uvedený diagram ukazuje všechna ID z obou tabulek, která přežila spojení.

Schéma funkce full_join v dplyru keeping všech šest ID a doplnění chybějících hodnot pomocí NA

full_join(df_primary, df_secondary, by = 'ID')

Výstup:

## # A tibble: 6 x 3
##      ID   y.x   y.y
##   <chr> <dbl> <dbl>
## 1     A     5    30
## 2     B     5    21
## 3     C     8    22
## 4     D     0    25
## 5     F     9    NA
## 6     E    NA    29

Více párů klíčů

V neposlední řadě můžeme mít v naší datové sadě více klíčů. Vezměte si následující datovou sadu, kde máme roky a seznam produktů zakoupených zákazníkem. Snímek obrazovky níže ukazuje dvě tabulky a sloupce ID a rok, které společně identifikují řádek.

Dva datové rámce sdílející složený klíč složený ze sloupců ID a rok

Pokud obě tabulky spojíme pouze na základě ID, každý rok se porovná s každým rokem a počet řádků se exploduje. Abychom tuto situaci napravili, můžeme předat dvě proměnné typu pár klíčů. ID a rok, které se objevují v obou datových sadách. Ke sloučení tabulky 1 a tabulky 2 můžeme použít následující kód:

df_primary <- tribble(
  ~ID, ~year, ~items,
  "A", 2015,3,
  "A", 2016,7,
  "A", 2017,6,
  "B", 2015,4,
  "B", 2016,8,
  "B", 2017,7,
  "C", 2015,4,
  "C", 2016,6,
  "C", 2017,6)
df_secondary <- tribble(
  ~ID, ~year, ~prices,
  "A", 2015,9,
  "A", 2016,8,
  "A", 2017,12,
  "B", 2015,13,
  "B", 2016,14,
  "B", 2017,6,
  "C", 2015,15,
  "C", 2016,15,
  "C", 2017,13)
left_join(df_primary, df_secondary, by = c('ID', 'year'))

Výstup:

## # A tibble: 9 x 4
##      ID  year items prices
##   <chr> <dbl> <dbl>  <dbl>
## 1     A  2015     3      9
## 2     A  2016     7      8
## 3     A  2017     6     12
## 4     B  2015     4     13
## 5     B  2016     8     14
## 6     B  2017     7      6
## 7     C  2015     4     15
## 8     C  2016     6     15
## 9     C  2017     6     13

Od verze dplyr 1.1.0 (leden 2023) lze stejný klíč zapsat jako join_by(ID, year) a dplyr nyní varuje před neočekávanými shodami typu „mnoho k mnoha“, protože Oznámení o připojení k dplyr 1.1.0 vysvětluje.

Funkce čištění dat v R

Sloučení řeší pouze polovinu problému, protože sloučenou tabulku je stále třeba přetvořit. Následují čtyři důležité funkce pro uklizení (čištění) dat:

funkce Objektivní Argumenty
shromáždit() Transformujte data z širokých na dlouhé (data, klíč, hodnota, na.rm = FALSE)
šíření() Transformujte data z dlouhých na široké (data, klíč, hodnota)
samostatný() Rozdělte jednu proměnnou na dvě (data, sloupec, do, sep = „“, odstranit = TRUE)
sjednotit() Sjednoťte dvě proměnné do jedné (data, sloupec, koncentrace, oddělovač = „“, odstranit = PRAVDA)

Poznámka k verzi: Funkce gather() a spread() byly v tidyru 1.0.0 nahrazeny funkcemi pivot_longer() a pivot_wider() a v tidyru 1.3.0 funkce separate() nahrazena rodinou funkcí separate_wider_delim(). Nahrazená funkce stále běží, takže každý níže uvedený příklad funguje, ale nový kód by měl preferovat novější rodiny funkcí zobrazené v otočná viněta TidyrFunkce . unite() zůstává aktuální.

Pro manipulaci, čištění a vizualizaci dat používáme balíček tidyr, který je součástí kolekce tidyverse. Pokud byl R nainstalován s Anacondou, je balíček již k dispozici z https://anaconda.org/r/r-tidyr.

Pokud ještě není nainstalován, zadejte následující příkaz pro instalaci tidyr:

install.packages("tidyr")

shromáždit()

Cílem funkce gather() je transformovat data ze širokých na dlouhé.

Syntax

gather(data, key, value, na.rm = FALSE)
Arguments:
-data: The data frame used to reshape the dataset 
-key: Name of the new column created
-value: Select the columns used to fill the key column
-na.rm: Remove missing values. FALSE by default

Příklad

Níže si můžeme vizualizovat koncept reshaping od široké po dlouhou. Chceme vytvořit jeden sloupec s názvem růst, vyplněný řádky čtvrtletních proměnných. Obrázek níže ukazuje širokou tabulku vlevo a přetvořenou dlouhou tabulku vpravo.

Rešaping převod široké čtvrtletní tabulky do dlouhého formátu pomocí funkce Tidyr Gather

library(tidyr)
# Create a messy dataset
messy <- data.frame(
  country = c("A", "B", "C"),
  q1_2017 = c(0.03, 0.05, 0.01),
  q2_2017 = c(0.05, 0.07, 0.02),
  q3_2017 = c(0.04, 0.05, 0.01),
  q4_2017 = c(0.03, 0.02, 0.04))
messy

Výstup:

##   country q1_2017 q2_2017 q3_2017 q4_2017
## 1       A    0.03    0.05    0.04    0.03
## 2       B    0.05    0.07    0.05    0.02
## 3       C    0.01    0.02    0.01    0.04
# Reshape the data
tidier <-messy %>%
gather(quarter, growth, q1_2017:q4_2017)
tidier

Výstup:

##    country quarter growth
## 1        A q1_2017   0.03
## 2        B q1_2017   0.05
## 3        C q1_2017   0.01
## 4        A q2_2017   0.05
## 5        B q2_2017   0.07
## 6        C q2_2017   0.02
## 7        A q3_2017   0.04
## 8        B q3_2017   0.05
## 9        C q3_2017   0.01
## 10       A q4_2017   0.03
## 11       B q4_2017   0.02
## 12       C q4_2017   0.04

Ve funkci gather() vytvoříme dvě nové proměnné, quarter a growth, protože naše původní datová sada má jednu skupinovou proměnnou, country, a páry klíč-hodnota. V tidyr 1.0.0 a novějších verzích je stejná změna tvaru zapsána jako pivot_longer(messy, cols = q1_2017:q4_2017, names_to = „quarter“, values_to = „growth“).

šíření()

Funkce spread() dělá opak funkce gather().

Syntax

spread(data, key, value)
arguments: 
data: The data frame used to reshape the dataset
key: Column to reshape long to wide
value: Rows used to fill the new column

Příklad

Uspořádanější datovou sadu můžeme přetvořit zpět na chaotickou pomocí spread().

# Reshape the data
messy_1 <- tidier %>%
  spread(quarter, growth) 
messy_1

Výstup:

##   country q1_2017 q2_2017 q3_2017 q4_2017
## 1       A    0.03    0.05    0.04    0.03
## 2       B    0.05    0.07    0.05    0.02
## 3       C    0.01    0.02    0.01    0.04

Moderní ekvivalent je pivot_wider(tidier, names_from = čtvrtletí, values_from = růst).

samostatný()

Funkce separate() rozdělí sloupec na dva podle oddělovače. Tato funkce je užitečná v situacích, kdy je proměnná datum. Naše analýza může vyžadovat zaměření na měsíc a rok a chceme sloupec rozdělit na dvě nové proměnné.

Syntax

separate(data, col, into, sep= "", remove = TRUE)
arguments:
-data: The data frame used to reshape the dataset 
-col: The column to split
-into: The name of the new variables
-sep: Indicates the symbol used that separates the variable, i.e.:  "-", "_", "&"
-remove: Remove the old column. By default sets to TRUE.

Příklad

V přehlednější datové sadě můžeme oddělit čtvrtletí od roku použitím funkce separát () .

separate_tidier <-tidier %>%
separate(quarter, c("Qrt", "year"), sep ="_")
head(separate_tidier)

Výstup:

##   country Qrt year growth
## 1       A  q1 2017   0.03
## 2       B  q1 2017   0.05
## 3       C  q1 2017   0.01
## 4       A  q2 2017   0.05
## 5       B  q2 2017   0.07
## 6       C  q2 2017   0.02

sjednotit()

Funkce unite() zřetězí dva sloupce do jednoho.

Syntax

unite(data, col, conc ,sep= "", remove = TRUE)
arguments:
-data: The data frame used to reshape the dataset 
-col: Name of the new column
-conc: Name of the columns to concatenate
-sep: Indicates the symbol used that unites the variable, i.e:  "-", "_", "&"
-remove: Remove the old columns. By default, sets to TRUE

Příklad

Ve výše uvedeném příkladu jsme oddělili čtvrtletí od roku. Co když je chceme sloučit? Použijeme následující kód:

unit_tidier <- separate_tidier %>%
  unite(Quarter, Qrt, year, sep ="_")
head(unit_tidier)

Výstup:

##   country Quarter growth
## 1       A q1_2017   0.03
## 2       B q1_2017   0.05
## 3       C q1_2017   0.01
## 4       A q2_2017   0.05
## 5       B q2_2017   0.07
## 6       C q2_2017   0.02

Přepracovaný datový rámec je nyní připraven pro modelovací kroky popsané ve zbytku Série tutoriálů R.

Nejčastější dotazy

merge() vyjadřuje každé spojení pomocí příznaků all, all.x a all.y, zatímco dplyr pojmenovává chování v samotném slovesu. dplyr také zachovává původní pořadí řádků a vrací tibble. Základní trasa R je pokryta v sloučení datových rámců průvodce.

Jsou to filtrovací spojení, takže nikdy nepřidávají sloupce. semi_join(x, y) uchovává řádky x, které mají shodu v y, a anti_join(x, y) uchovává řádky, které ji nemají. Oba jsou užitečné pro audit klíčů před mutujícím spojením.

Namapujte je explicitně pomocí by = c(“ID” = “customer_id”) nebo použijte novější pomocnou funkci join_by(ID == customer_id). Bez mapovánípingFunkce dplyr vyhledává shody s každým sdíleným názvem sloupce, což může výsledek nenápadně zúžit nebo naopak zvětšit.

Hodnota klíče se opakuje na obou stranách, takže se vytvoří každá kombinace. Nejprve zkontrolujte duplicated() na každém klíči, agregujte stranu typu „many“ nebo předejte relation = „many-to-many“ pro určení záměru. dplyr varuje před neočekávanými shodami typu „many-to-many“.

filter() vybírá řádky, select() vybírá sloupce, arrange() kouzlaFunkce mutate() přidává sloupce a summarize() sbaluje skupiny vytvořené funkcí group_by(). Roupa vkládá jeden výsledek do dalšího slovesa; %>% je součástí dplyr a |> je nativní pro R.

Asistenti umělé inteligence mohou profilovat datový rámec, označit duplicitní nebo chybně zadané klíče před spojením a navrhnout změnu.ping sloveso, které odpovídá rozvržení, a vysvětlete náhlou změnu počtu řádků srozumitelným jazykem. Vždy znovu spusťte kód a sami zkontrolujte rozměry.

Ano. GitHub Copilot Funguje v RStudio Desktop 2023.09.0 a novějších verzích a dokončuje spojení a pivotování z komentáře. Posit poznamenává, že návrhy nejsou deterministické, proto si před spuštěním zkontrolujte každý vygenerovaný řádek.

Řetězte spojení nebo složte seznam pomocí funkce Reduce(function(x, y) left_join(x, y, by = “ID”), list(df1, df2, df3)). Funkce purrr::reduce() provede totéž. Po každém kroku zkontrolujte nrow(), protože duplicitní klíče se napříč spojeními skládají.

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