R package tidyr è e so novi funzioni pivot_longer è pivot_wider
Poney urdinatu inclusu in u core di una di e biblioteche più populari in a lingua R - ordinatu.
U scopu principale di u pacchettu hè di portà i dati in una forma precisa.
Dighjà dispunibule nantu à Habré publicazione dedicatu à stu pacchettu, ma data di 2015. È vogliu cuntà di i cambiamenti più attuali, chì sò stati annunziati uni pochi ghjorni fà da u so autore, Hedley Wickham.
SJK: Gather () è sparghje () seranu obsoleti ?
Hadley Wickham: In una certa misura. Ùn avemu più ricumandemu l'usu di queste funzioni è correggerà i bug in elli, ma continuanu à esse prisenti in u pacchettu in u so statu attuale.
Cuntenuti
Sè vo site interessatu in l'analisi di dati, pudete esse interessatu in u mo telegram и fratii canali. A maiò parte di u cuntenutu hè dedicatu à a lingua R.
Goal urdinatu - aiutanu à purtà i dati à una forma chjamata neat. I dati puliti sò dati induve:
Ogni variabile hè in una colonna.
Ogni osservazione hè una stringa.
Ogni valore hè una cellula.
Hè assai più faciule è più còmuda di travaglià cù e dati chì sò presentati in dati ordinati quandu facenu analisi.
Funzioni principali incluse in u pacchettu tidyr
tidyr cuntene un inseme di funzioni pensate per trasfurmà e tavule:
fill() - riempie i valori mancanti in una colonna cù i valori precedenti;
separate() - divide un campu in parechji cù un separatore;
unite() - esegue l'operazione di cumminà parechji campi in unu, l'azzione inversa di a funzione separate();
pivot_longer() - una funzione chì cunvertisce dati da formatu largu à furmatu longu;
pivot_wider() - una funzione chì cunvertisce dati da furmatu longu à furmatu largu. L'operazione inversa di quella realizata da a funzione pivot_longer().
gather()obsolet - una funzione chì cunvertisce dati da formatu largu à furmatu longu;
spread()obsolet - una funzione chì cunvertisce dati da furmatu longu à furmatu largu. L'operazione inversa di quella realizata da a funzione gather().
Novu cuncettu per a cunversione di dati da u formatu largu à longu è viceversa
Nanzu, e funzioni eranu aduprate per stu tipu di trasfurmazioni gather() и spread(). Nantu à l'anni di esistenza di sti funzioni, hè diventatu evidenti chì per a maiò parte di l'utilizatori, cumpresu l'autore di u pacchettu, i nomi di sti funzioni è i so argumenti ùn eranu micca abbastanza evidenti, è hà causatu difficultà à truvà elli è capisce quale di queste funzioni cunvertisce. un quadru di data da u formatu largu à longu, è viceversa.
In questu sensu, in urdinatu Dui funzioni novi, impurtanti sò state aghjunte chì sò pensate per trasfurmà i frames di data.
Novità pivot_longer() и pivot_wider() sò stati inspirati da alcune di e funziunalità in u pacchettu cdata, creatu da John Mount è Nina Zumel.
Stallà a versione più attuale di tidyr 0.8.3.9000
Per installà a nova versione più attuale di u pacchettu urdinatu0.8.3.9000, induve e funzioni novi sò dispunibili, utilizate u codice seguente.
devtools::install_github("tidyverse/tidyr")
À u mumentu di a scrittura, queste funzioni sò solu dispunibili in a versione dev di u pacchettu in GitHub.
Transizione à e funzioni novi
In fatti, ùn hè micca difficiule di trasfirià script antichi per travaglià cù e funzioni novi; per capisce megliu, pigliaraghju un esempiu da a documentazione di e funzioni antichi è mostra cumu si facenu e stesse operazioni cù novi. pivot_*() funzioni.
Cunvertisce un furmatu largu à un furmatu longu.
Esempiu di codice da a documentazione di a funzione di raccolta
# example
library(dplyr)
stocks <- data.frame(
time = as.Date('2009-01-01') + 0:9,
X = rnorm(10, 0, 1),
Y = rnorm(10, 0, 2),
Z = rnorm(10, 0, 4)
)
# old
stocks_gather <- stocks %>% gather(key = stock,
value = price,
-time)
# new
stocks_long <- stocks %>% pivot_longer(cols = -time,
names_to = "stock",
values_to = "price")
Cunvertisce un furmatu longu à un furmatu largu.
Esempiu di codice da a documentazione di a funzione diffusa
# old
stocks_spread <- stocks_gather %>% spread(key = stock,
value = price)
# new
stock_wide <- stocks_long %>% pivot_wider(names_from = "stock",
values_from = "price")
Perchè in l'esempii sopra di travaglià cù pivot_longer() и pivot_wider(), in a tavula originale Gemiliana nisuna culonna listata in argumenti nomi_à и valori_à i so nomi deve esse in virgolette.
Un tavulinu chì vi aiuterà più facilmente à capisce cumu passà à travaglià cù un novu cuncettu urdinatu.
Nota da l'autore
Tuttu u testu quì sottu hè adattatu, diceraghju ancu traduzzione libera vignette da u situ ufficiale di a biblioteca tidyverse.
Un esempiu simplice di cunvertisce dati da u formatu largu à longu
pivot_longer () - rende i setti di dati più longu riducendu u nùmeru di colonne è aumentendu u numeru di fila.
Per eseguisce l'esempii presentati in l'articulu, avete prima bisognu di cunnette i pacchetti necessarii:
library(tidyr)
library(dplyr)
library(readr)
Diciamu chì avemu un tavulu cù i risultati di una indagine chì (frà altre cose) hà dumandatu à e persone nantu à a so religione è u redditu annuale:
Questa tavula cuntene i dati di religione di i rispondenti in fila, è i livelli di redditu sò spargugliati in i nomi di colonna. U numeru di rispondenti da ogni categuria hè almacenatu in i valori di e cellule à l'intersezzione di a religione è u livellu di ingressu. Per purtà a tavula in un formatu pulito è currettu, hè abbastanza à aduprà pivot_longer():
Primu argumentu colli, descrive quale culonni deve esse unitu. In questu casu, tutte e culonne eccettu tempu.
argumentu nomi_à dà u nome di a variàbile chì serà creatu da i nomi di e culonni chì avemu cuncatenatu.
valori_à dà u nome di una variàbile chì serà creata da i dati guardati in i valori di e cellule di e culonni fusionati.
Quaternu
Questa hè una nova funziunalità di u pacchettu urdinatu, chì prima ùn era micca dispunibule quandu travagliava cù e funzioni legacy.
Una specificazione hè un quadru di dati, ogni fila di quale currisponde à una colonna in u novu quadru di data di output, è duie colonne speciali chì cumincianu cù:
.name cuntene u nome di a colonna originale.
.valore cuntene u nome di a colonna chì cuntene i valori di e cellule.
I culonni rimanenti di a specificazione riflettenu cumu a nova colonna mostrarà u nome di e colonne compresse da .name.
A specificazione descrizanu i metadati guardati in un nome di colonna, cù una fila per ogni colonna è una colonna per ogni variàbile, cumminata cù u nome di a colonna, sta definizione pò parè cunfusa à u mumentu, ma dopu avè vistu un pocu di esempi diventerà assai. più chjaru.
U puntu di a specificazione hè chì pudete ritruvà, mudificà è definisce novi metadati per u dataframe chì hè cunvertitu.
Per travaglià cù specificazioni quandu cunvertisce una tavola da un formatu largu à un formatu longu, utilizate a funzione pivot_longer_spec().
Cumu funziona sta funzione hè chì piglia ogni quadru di data è genera i so metadati in a manera descritta sopra.
Cum'è un esempiu, pigliemu u set di dati who chì hè furnitu cù u pacchettu urdinatu. Stu dataset cuntene infurmazione furnita da l'urganizazione internaziunale di salute nantu à l'incidenza di a tuberculosi.
who
#> # A tibble: 7,240 x 60
#> country iso2 iso3 year new_sp_m014 new_sp_m1524 new_sp_m2534
#> <chr> <chr> <chr> <int> <int> <int> <int>
#> 1 Afghan… AF AFG 1980 NA NA NA
#> 2 Afghan… AF AFG 1981 NA NA NA
#> 3 Afghan… AF AFG 1982 NA NA NA
#> 4 Afghan… AF AFG 1983 NA NA NA
#> 5 Afghan… AF AFG 1984 NA NA NA
#> 6 Afghan… AF AFG 1985 NA NA NA
#> 7 Afghan… AF AFG 1986 NA NA NA
#> 8 Afghan… AF AFG 1987 NA NA NA
#> 9 Afghan… AF AFG 1988 NA NA NA
#> 10 Afghan… AF AFG 1989 NA NA NA
#> # … with 7,230 more rows, and 53 more variables
Custruemu a so specificazione.
spec <- who %>%
pivot_longer_spec(new_sp_m014:newrel_f65, values_to = "count")
campi paese, isoxnumx, isoxnumx sò digià variabili. U nostru compitu hè di flip the columns cun new_sp_m014 nantu newrel_f65.
I nomi di sti culonni guardanu l'infurmazioni seguenti:
Prefissu new_ indica chì a colonna cuntene dati nantu à novi casi di tuberculosis, u quadru di data attuale cuntene infurmazioni solu nantu à e malatie novi, cusì stu prefissu in u cuntestu attuale ùn porta micca significatu.
sp/rel/sp/ep descrive un metudu per diagnosticà una malatia.
m/f sessu di u paziente.
014/1524/2535/3544/4554/65 fascia di età di i pazienti.
Pudemu split sti culonni usendu a funzione extract()usendu l'espressione regulare.
Infine, per applicà a specificazione chì avemu creatu à u quadru di data originale chì avemu bisognu di utilizà un argumentu spec in funzione pivot_longer().
who %>% pivot_longer(spec = spec)
#> # A tibble: 405,440 x 8
#> country iso2 iso3 year diagnosis gender age count
#> <chr> <chr> <chr> <int> <chr> <fct> <ord> <int>
#> 1 Afghanistan AF AFG 1980 sp m 014 NA
#> 2 Afghanistan AF AFG 1980 sp m 1524 NA
#> 3 Afghanistan AF AFG 1980 sp m 2534 NA
#> 4 Afghanistan AF AFG 1980 sp m 3544 NA
#> 5 Afghanistan AF AFG 1980 sp m 4554 NA
#> 6 Afghanistan AF AFG 1980 sp m 5564 NA
#> 7 Afghanistan AF AFG 1980 sp m 65 NA
#> 8 Afghanistan AF AFG 1980 sp f 014 NA
#> 9 Afghanistan AF AFG 1980 sp f 1524 NA
#> 10 Afghanistan AF AFG 1980 sp f 2534 NA
#> # … with 405,430 more rows
Tuttu ciò chì avemu appena fattu pò esse schematicamente raffiguratu cusì:
Specificazione cù valori multipli (.value)
In l'esempiu sopra, a colonna di specificazione .valore cuntene solu un valore, in a maiò parte di i casi questu hè u casu.
Ma in ocasioni pò esse una situazione quandu avete bisognu di cullà dati da colonne cù diversi tipi di dati in valori. Utilizà una funzione legata spread() questu seria abbastanza difficiule di fà.
L'esempiu sottu hè pigliatu da vignette à u pacchettu dati.tavula.
U quadru di data creatu cuntene dati nantu à i zitelli di una famiglia in ogni linea. E famiglie ponu avè unu o dui figlioli. Per ogni zitellu, i dati sò furniti nantu à a data di nascita è u sessu, è i dati per ogni zitellu sò in colonne separate; u nostru compitu hè di portà queste dati à u formatu currettu per l'analisi.
Per piacè nutate chì avemu duie variàbili cù infurmazioni nantu à ogni zitellu: u so sessu è a data di nascita (columne cù u prefissu). D dop cuntene data di nascita, colonne cù prefissu genere cuntene u sessu di u zitellu). U risultatu aspittatu hè chì deve esse appare in culonni separati. Pudemu fà questu generendu una specificazione in quale a colonna .value averà dui significati diffirenti.
spec <- family %>%
pivot_longer_spec(-family) %>%
separate(col = name, into = c(".value", "child"))%>%
mutate(child = parse_number(child))
#> # A tibble: 4 x 3
#> .name .value child
#> <chr> <chr> <dbl>
#> 1 dob_child1 dob 1
#> 2 dob_child2 dob 2
#> 3 gender_child1 gender 1
#> 4 gender_child2 gender 2
Allora, andemu à piglià un ochju passu à passu à l'azzioni realizati da u codice sopra.
pivot_longer_spec(-family) - crea una specificazione chì cumpressa tutte e colonne esistenti eccettu a colonna di famiglia.
separate(col = name, into = c(".value", "child")) - split the column .name, chì cuntene i nomi di i campi di fonte, usendu u underscore è inserendu i valori resultanti in e colonne .valore и Zitellu.
mutate(child = parse_number(child)) - trasfurmà i valori di u campu Zitellu da u testu à u tipu di dati numericu.
Avà pudemu applicà a specificazione resultanti à u dataframe originale è portà a tavula à a forma desiderata.
Avemu aduprà argumentu na.rm = TRUE, perchè a forma attuale di e dati forza a creazione di fila extra per osservazioni inesistenti. Perchè a famiglia 2 hà solu un zitellu, na.rm = TRUE guarantisci chì a famiglia 2 hà una fila in u output.
Cunvertisce i frames di data da u formatu longu à u largu
pivot_wider() - hè a trasfurmazioni inversa, è viceversa aumenta u numeru di culonni di u quadru di data riducendu u numeru di fila.
Stu tipu di trasfurmazioni hè estremamente raramente utilizatu per portà e dati in una forma precisa, in ogni modu, sta tecnica pò esse utile per creà tabelle pivot usate in presentazioni, o per integrazione cù qualchi altri strumenti.
In fatti, e funzioni pivot_longer() и pivot_wider() sò simmetrici, è produci azzioni inverse l'una à l'altru, vale à dì: df %>% pivot_longer(spec = spec) %>% pivot_wider(spec = spec) и df %>% pivot_wider(spec = spec) %>% pivot_longer(spec = spec) restituverà u df originale.
L'esempiu più simplice di cunvertisce una tavula in un furmatu largu
Per dimustrà cumu funziona a funzione pivot_wider() avemu aduprà u dataset scontri_pesci, chì guarda infurmazione nantu à cumu diverse stazioni registranu u muvimentu di pesci longu u fiume.
#> # A tibble: 114 x 3
#> fish station seen
#> <fct> <fct> <int>
#> 1 4842 Release 1
#> 2 4842 I80_1 1
#> 3 4842 Lisbon 1
#> 4 4842 Rstr 1
#> 5 4842 Base_TD 1
#> 6 4842 BCE 1
#> 7 4842 BCW 1
#> 8 4842 BCE2 1
#> 9 4842 BCW2 1
#> 10 4842 MAE 1
#> # … with 104 more rows
In a maiò parte di i casi, sta tavula serà più informativa è più faciule d'utilizà se presentate infurmazioni per ogni stazione in una colonna separata.
fish_encounters %>% pivot_wider(names_from = station, values_from = seen)
#> # A tibble: 19 x 12
#> fish Release I80_1 Lisbon Rstr Base_TD BCE BCW BCE2 BCW2 MAE
#> <fct> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
#> 1 4842 1 1 1 1 1 1 1 1 1 1
#> 2 4843 1 1 1 1 1 1 1 1 1 1
#> 3 4844 1 1 1 1 1 1 1 1 1 1
#> 4 4845 1 1 1 1 1 NA NA NA NA NA
#> 5 4847 1 1 1 NA NA NA NA NA NA NA
#> 6 4848 1 1 1 1 NA NA NA NA NA NA
#> 7 4849 1 1 NA NA NA NA NA NA NA NA
#> 8 4850 1 1 NA 1 1 1 1 NA NA NA
#> 9 4851 1 1 NA NA NA NA NA NA NA NA
#> 10 4854 1 1 NA NA NA NA NA NA NA NA
#> # … with 9 more rows, and 1 more variable: MAW <int>
Stu settore di dati registra solu l'infurmazioni quandu i pesci sò stati rilevati da a stazione, i.e. se un pesciu ùn hè statu registratu da una stazione, allora sta dati ùn saranu micca in a tavula. Questu significa chì l'output serà pienu di NA.
In ogni casu, in questu casu sapemu chì l'absenza di un registru significa chì u pesciu ùn hè micca vistu, cusì pudemu usà l'argumentu. values_fill in funzione pivot_wider() è riempie questi valori mancanti cù zeri:
Generazione di un nome di colonna da parechje variabili fonte
Imagine chì avemu una tavola chì cuntene una cumminazione di produttu, paese è annu. Per generà un quadru di data di prova, pudete eseguisce u codice seguente:
df <- expand_grid(
product = c("A", "B"),
country = c("AI", "EI"),
year = 2000:2014
) %>%
filter((product == "A" & country == "AI") | product == "B") %>%
mutate(value = rnorm(nrow(.)))
#> # A tibble: 45 x 4
#> product country year value
#> <chr> <chr> <int> <dbl>
#> 1 A AI 2000 -2.05
#> 2 A AI 2001 -0.676
#> 3 A AI 2002 1.60
#> 4 A AI 2003 -0.353
#> 5 A AI 2004 -0.00530
#> 6 A AI 2005 0.442
#> 7 A AI 2006 -0.610
#> 8 A AI 2007 -2.77
#> 9 A AI 2008 0.899
#> 10 A AI 2009 -0.106
#> # … with 35 more rows
U nostru compitu hè di espansione u quadru di dati in modu chì una colonna cuntene dati per ogni cumminazione di pruduttu è paese. Per fà questu, basta à passà l'argumentu nomi_da un vettore chì cuntene i nomi di i campi da unisce.
Pudete ancu applicà specificazioni à una funzione pivot_wider(). Ma quandu sottumessi à pivot_wider() a specificazione faci a cunversione opposta pivot_longer(): I culonni specificati in .name, usendu valori da .valore e altre colonne.
Per questu set di dati, pudete generà una specificazione persunalizata se vulete chì ogni paese possibbili è cumminazione di produttu hà a so propria colonna, micca solu quelli prisenti in i dati:
#> # A tibble: 4 x 4
#> .name product country .value
#> <chr> <chr> <chr> <chr>
#> 1 A_AI A AI value
#> 2 A_EI A EI value
#> 3 B_AI B AI value
#> 4 B_EI B EI value
df %>% pivot_wider(spec = spec) %>% head()
#> # A tibble: 6 x 5
#> year A_AI A_EI B_AI B_EI
#> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 2000 -2.05 NA 0.607 1.20
#> 2 2001 -0.676 NA 1.65 -0.114
#> 3 2002 1.60 NA -0.0245 0.501
#> 4 2003 -0.353 NA 1.30 -0.459
#> 5 2004 -0.00530 NA 0.921 -0.0589
#> 6 2005 0.442 NA -1.55 0.594
Parechji esempii avanzati di travaglià cù u novu cuncettu tidyr
Pulizia di e dati utilizendu u Censu di i Stati Uniti Revenu è Rent dataset cum'è un esempiu.
Set di dati us_rent_income cuntene infurmazione mediana di redditu è affittu per ogni statu in i Stati Uniti per 2017 (set di dati dispunibule in u pacchettu tidycensus).
us_rent_income
#> # A tibble: 104 x 5
#> GEOID NAME variable estimate moe
#> <chr> <chr> <chr> <dbl> <dbl>
#> 1 01 Alabama income 24476 136
#> 2 01 Alabama rent 747 3
#> 3 02 Alaska income 32940 508
#> 4 02 Alaska rent 1200 13
#> 5 04 Arizona income 27517 148
#> 6 04 Arizona rent 972 4
#> 7 05 Arkansas income 23789 165
#> 8 05 Arkansas rent 709 5
#> 9 06 California income 29454 109
#> 10 06 California rent 1358 3
#> # … with 94 more rows
In a forma in quale i dati sò guardati in u dataset us_rent_income travaglià cun elli hè estremamente inconveniente, cusì vulemu creà un settore di dati cù colonne: Appartamenti, affittu_moe, ghjuntu, income_moe. Ci hè parechje manere di creà sta specificazione, ma u puntu principale hè chì avemu bisognu di generà ogni cumminazione di valori variabili è stima / moeè dopu generà u nome di a colonna.
Calchì volta portà un settore di dati in a forma desiderata richiede parechji passi.
Dataset world_bank_pop cuntene dati di u Bancu Mundiale nantu à a pupulazione di ogni paese trà 2000 è 2018.
U nostru scopu hè di creà un set di dati pulito cù ogni variabile in a so propria colonna. Ùn hè chjaru esattamente ciò chì i passi sò necessarii, ma avemu da principià cù u prublema più evidenti: l'annu hè spargugliatu in parechje colonne.
Per risolve questu, avete bisognu di utilizà a funzione pivot_longer().
U prossimu passu hè di guardà a variabile indicatore. pop2 %>% count(indicator)
#> # A tibble: 4 x 2
#> indicator n
#> <chr> <int>
#> 1 SP.POP.GROW 4752
#> 2 SP.POP.TOTL 4752
#> 3 SP.URB.GROW 4752
#> 4 SP.URB.TOTL 4752
Induve SP.POP.GROW hè a crescita di a pupulazione, SP.POP.TOTL hè a pupulazione tutale, è SP.URB. * listessa cosa, ma solu per i zoni urbani. Dividemu sti valori in dui variàbili: area - area (totale o urbana) è una variàbile chì cuntene dati reali (populazione o crescita):
A tabulazione di sta lista hè abbastanza difficiule perchè ùn ci hè micca variabile chì identifica quale dati appartene à quale cuntattu. Pudemu riparà questu nutendu chì i dati di ogni novu cuntattu cumincianu cù "nome", cusì pudemu creà un identificatore unicu è l'incrementu da unu ogni volta chì a colonna di u campu cuntene u valore "nome":
#> # A tibble: 6 x 3
#> field value person_id
#> <chr> <chr> <int>
#> 1 name Jiena McLellan 1
#> 2 company Toyota 1
#> 3 name John Smith 2
#> 4 company google 2
#> 5 email [email protected] 2
#> 6 name Huxley Ratcliffe 3
Avà chì avemu un ID unicu per ogni cuntattu, pudemu turnà u campu è u valore in colonne:
#> # A tibble: 3 x 4
#> person_id name company email
#> <int> <chr> <chr> <chr>
#> 1 1 Jiena McLellan Toyota <NA>
#> 2 2 John Smith google [email protected]
#> 3 3 Huxley Ratcliffe <NA> <NA>
cunchiusioni
A mo opinione persunale hè chì u novu cuncettu urdinatu veramente più intuitive, è significativamente superiore in funziunalità à e funzioni legacy spread() и gather(). Speru chì questu articulu vi hà aiutatu à trattà pivot_longer() и pivot_wider().