ProHoster > Blog > Stjórnsýsla > R pakki tidyr og nýju aðgerðir hans pivot_longer og pivot_wider
R pakki tidyr og nýju aðgerðir hans pivot_longer og pivot_wider
Pakkinn snyrtilegt innifalinn í kjarna eins vinsælasta bókasafnsins á R tungumálinu - snyrtilegur.
Megintilgangur pakkans er að koma gögnunum á rétt form.
Nú þegar fáanlegt á Habré útgáfu tileinkað þessum pakka, en hann nær aftur til ársins 2015. Og ég vil segja ykkur frá nýjustu breytingunum, sem höfundur hennar, Hedley Wickham, tilkynnti fyrir nokkrum dögum.
SJK: Verður safna() og dreifa() úrelt?
Hadley Wickham: Að einhverju leyti. Við munum ekki lengur mæla með notkun þessara aðgerða og laga villur í þeim, en þær munu halda áfram að vera til staðar í pakkanum í núverandi ástandi.
efni
Ef þú hefur áhuga á gagnagreiningu gætirðu haft áhuga á mínum símskeyti и YouTube rásir. Mest af efninu er tileinkað R tungumálinu.
Markmið snyrtilegt — hjálpa þér að koma gögnunum á svokallað snyrtilegt form. Snyrtileg gögn eru gögn þar sem:
Hver breyta er í dálki.
Hver athugun er strengur.
Hvert gildi er klefi.
Það er mun auðveldara og þægilegra að vinna með gögn sem eru sett fram í snyrtilegum gögnum þegar unnið er að greiningu.
Helstu aðgerðir innifalinn í tidyr pakkanum
tidyr inniheldur mengi aðgerða sem eru hönnuð til að umbreyta töflum:
fill() - fylla upp gildi sem vantar í dálk með fyrri gildum;
separate() — skiptir einu sviði í nokkra með því að nota skilju;
unite() — framkvæmir þá aðgerð að sameina nokkur svið í eitt, andhverfa aðgerð fallsins separate();
pivot_longer() — aðgerð sem breytir gögnum úr breiðsniði í langsnið;
pivot_wider() - aðgerð sem breytir gögnum úr löngu sniði í breitt snið. Öfug aðgerð þess sem aðgerðin framkvæmir pivot_longer().
gather()gamaldags — aðgerð sem breytir gögnum úr breiðsniði í langsnið;
spread()gamaldags - aðgerð sem breytir gögnum úr löngu sniði í breitt snið. Öfug aðgerð þess sem aðgerðin framkvæmir gather().
Ný hugmynd til að umbreyta gögnum úr breitt í langt snið og öfugt
Áður voru föll notuð fyrir þessa tegund umbreytinga gather() и spread(). Í gegnum árin sem þessar aðgerðir voru til varð augljóst að fyrir flesta notendur, þar á meðal höfund pakkans, voru nöfn þessara falla og rök þeirra ekki alveg augljós og ollu erfiðleikum við að finna þær og skilja hvaða af þessum aðgerðum breytir dagsetningarrammi frá breiðu til löngu sniði og öfugt.
Í þessu sambandi, í snyrtilegt Tveimur nýjum mikilvægum aðgerðum hefur verið bætt við sem eru hannaðar til að umbreyta dagsetningarrömmum.
Nýir eiginleikar pivot_longer() и pivot_wider() voru innblásin af sumum eiginleikum pakkans cdata, búin til af John Mount og Ninu Zumel.
Setur upp nýjustu útgáfuna af tidyr 0.8.3.9000
Til að setja upp nýjustu útgáfuna af pakkanum snyrtilegt0.8.3.9000, þar sem nýir eiginleikar eru fáanlegir, notaðu eftirfarandi kóða.
devtools::install_github("tidyverse/tidyr")
Þegar þetta er skrifað eru þessar aðgerðir aðeins fáanlegar í þróunarútgáfu pakkans á GitHub.
Umskipti yfir í nýja eiginleika
Reyndar er ekki erfitt að flytja gömul forskrift til að vinna með nýjar aðgerðir; til að skilja betur mun ég taka dæmi úr skjölum um gamlar aðgerðir og sýna hvernig sömu aðgerðir eru framkvæmdar með nýjum pivot_*() aðgerðir.
Umbreyttu breitt sniði í langt snið.
Dæmi um kóða úr skjölum fyrir söfnunaraðgerðina
# 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")
Breytir löngu sniði í breitt snið.
Dæmi um kóða úr dreifingaraðgerðaskjölum
# old
stocks_spread <- stocks_gather %>% spread(key = stock,
value = price)
# new
stock_wide <- stocks_long %>% pivot_wider(names_from = "stock",
values_from = "price")
Vegna þess að í ofangreindum dæmum um að vinna með pivot_longer() и pivot_wider(), í upprunalegu töflunni birgðir engir dálkar skráðir í rökum nöfn_til и gildi_til nöfn þeirra verða að vera innan gæsalappa.
Tafla sem auðveldar þér að finna út hvernig á að skipta yfir í að vinna með nýtt hugtak snyrtilegt.
Athugasemd frá höfundi
Allur textinn hér að neðan er aðlögunarhæfur, ég myndi jafnvel segja frjáls þýðing vinjettur frá opinberu vefsíðunni tidyverse bókasafnsins.
Einfalt dæmi um að umbreyta gögnum úr breitt í langt snið
pivot_longer () — gerir gagnasett lengri með því að fækka dálkum og fjölga línum.
Til að keyra dæmin sem kynnt eru í greininni þarftu fyrst að tengja nauðsynlega pakka:
library(tidyr)
library(dplyr)
library(readr)
Segjum að við höfum töflu með niðurstöðum könnunar sem (meðal annars) spurði fólk um trú þeirra og árstekjur:
Þessi tafla inniheldur trúarupplýsingar svarenda í röðum og tekjustig eru dreifð yfir dálkanöfn. Fjöldi svarenda úr hverjum flokki er geymdur í frumugildum á mótum trúarbragða og tekjustigs. Til að koma töflunni í snyrtilegt, rétt snið er nóg að nota pivot_longer():
Fyrstu rök kraga, lýsir hvaða dálkum þarf að sameina. Í þessu tilviki eru allir dálkar nema tími.
Rök nöfn_til gefur nafn breytunnar sem verður til úr nöfnum dálkanna sem við sameinuðum.
gildi_til gefur nafn breytu sem verður búin til úr gögnum sem eru geymd í gildum frumna í sameinuðu dálkunum.
Tæknilýsing
Þetta er ný virkni pakkans snyrtilegt, sem áður var ekki tiltækt þegar unnið var með eldri aðgerðir.
Forskrift er gagnarammi, þar sem hver röð samsvarar einum dálki í nýja framleiðsludagarammanum og tveir sérstakir dálkar sem byrja á:
. Nafn inniheldur upprunalega dálknafnið.
.gildi inniheldur nafn dálksins sem mun innihalda frumugildin.
Dálkarnir sem eftir eru í forskriftinni endurspegla hvernig nýi dálkurinn mun birta heiti þjappaðra dálka frá . Nafn.
Forskriftin lýsir lýsigögnum sem geymd eru í dálknafni, með einni línu fyrir hvern dálk og einum dálki fyrir hverja breytu, ásamt dálknafninu, þessi skilgreining kann að virðast ruglingsleg í augnablikinu, en eftir að hafa skoðað nokkur dæmi verður hún mikið skýrari.
Tilgangurinn með forskriftinni er að þú getur sótt, breytt og skilgreint ný lýsigögn fyrir gagnarammann sem verið er að breyta.
Til að vinna með forskriftir þegar töflu er breytt úr breitt sniði í langt snið, notaðu aðgerðina pivot_longer_spec().
Hvernig þessi aðgerð virkar er að hún tekur hvaða dagsetningarramma sem er og býr til lýsigögn á þann hátt sem lýst er hér að ofan.
Sem dæmi skulum við taka who dataset sem fylgir pakkanum snyrtilegt. Þetta gagnasafn inniheldur upplýsingar frá alþjóðlegu heilbrigðissamtökunum um tíðni berkla.
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
Við skulum byggja forskrift þess.
spec <- who %>%
pivot_longer_spec(new_sp_m014:newrel_f65, values_to = "count")
sviðum land, isoxnumx, isoxnumx eru nú þegar breytur. Verkefni okkar er að fletta dálkunum með new_sp_m014 á newrel_f65.
Nöfn þessara dálka geyma eftirfarandi upplýsingar:
Forskeyti new_ gefur til kynna að dálkurinn inniheldur gögn um ný tilfelli berkla, núverandi dagsetningarrammi inniheldur aðeins upplýsingar um nýja sjúkdóma, þannig að þetta forskeytið í núverandi samhengi hefur enga merkingu.
sp/rel/sp/ep lýsir aðferð til að greina sjúkdóm.
m/f kyn sjúklings.
014/1524/2535/3544/4554/65 aldursbil sjúklings.
Við getum skipt þessum dálkum með aðgerðinni extract()með því að nota reglulega tjáningu.
Að lokum, til að beita forskriftinni sem við bjuggum til á upprunalega dagsetningarrammann sem við þurfum að nota rök sérstakur í virkni 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
Allt sem við gerðum er hægt að lýsa með skýringarmynd sem hér segir:
Forskrift sem notar mörg gildi (.value)
Í dæminu hér að ofan, forskriftardálkurinn .gildi innihélt aðeins eitt gildi, í flestum tilfellum er þetta raunin.
En stundum getur komið upp sú staða þegar þú þarft að safna gögnum úr dálkum með mismunandi gagnategundir í gildum. Notkun eldri aðgerða spread() þetta væri frekar erfitt að gera.
Dæmið hér að neðan er tekið úr vinjettur að pakkanum gögn.tafla.
Stofnaður dagsetningarrammi inniheldur gögn um börn einnar fjölskyldu í hverri röð. Fjölskyldur geta átt eitt eða tvö börn. Fyrir hvert barn eru veitt gögn um fæðingardag og kyn og gögn fyrir hvert barn eru í sérstökum dálkum, verkefni okkar er að koma þessum gögnum á rétt snið til greiningar.
Vinsamlegast athugaðu að við höfum tvær breytur með upplýsingum um hvert barn: kyn þess og fæðingardag (dálkar með forskeytinu DOP innihalda fæðingardag, dálka með forskeyti kyn innihalda kyn barnsins). Áætluð niðurstaða er sú að þær ættu að birtast í aðskildum dálkum. Við getum gert þetta með því að búa til forskrift þar sem dálkurinn .value mun hafa tvær mismunandi merkingar.
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
Svo skulum við skoða skref fyrir skref aðgerðir sem framkvæmdar eru af ofangreindum kóða.
pivot_longer_spec(-family) - búðu til forskrift sem þjappar saman öllum núverandi dálkum nema fjölskyldudálknum.
separate(col = name, into = c(".value", "child")) - skiptu dálknum . Nafn, sem inniheldur nöfn upprunareitanna, með því að nota undirstrikið og slá inn gildin sem myndast í dálkana .gildi и barn.
mutate(child = parse_number(child)) — umbreyta reitgildunum barn frá texta til tölulegra gagnategunda.
Nú getum við beitt forskriftinni sem myndast á upprunalega gagnarammann og fært töfluna í æskilegt form.
Við notum rök na.rm = TRUE, vegna þess að núverandi form gagnanna þvingar til að búa til auka raðir fyrir athuganir sem ekki eru til. Vegna þess að fjölskylda 2 á aðeins eitt barn, na.rm = TRUE tryggir að fjölskylda 2 mun hafa eina röð í framleiðslunni.
Umbreytir dagsetningarrömmum úr löngu sniði í breitt snið
pivot_wider() - er andhverfa umbreyting, og öfugt eykur fjölda dálka dagsetningarrammans með því að fækka línum.
Þessi tegund umbreytinga er afar sjaldan notuð til að koma gögnum á nákvæmt form, en þessi tækni getur verið gagnleg til að búa til snúningstöflur sem notaðar eru í kynningum eða til að samþætta við önnur verkfæri.
Reyndar aðgerðir pivot_longer() и pivot_wider() eru samhverf og framkalla aðgerðir andstæða hver við aðra, þ.e. df %>% pivot_longer(spec = spec) %>% pivot_wider(spec = spec) и df %>% pivot_wider(spec = spec) %>% pivot_longer(spec = spec) mun skila upprunalegu df.
Einfaldasta dæmið um að breyta töflu í breitt snið
Til að sýna hvernig aðgerðin virkar pivot_wider() við munum nota gagnasafnið fiska_fundir, sem geymir upplýsingar um hvernig mismunandi stöðvar skrá flutning fiska meðfram ánni.
#> # 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
Í flestum tilfellum verður þessi tafla upplýsandi og auðveldari í notkun ef upplýsingar um hverja stöð eru settar fram í sérstökum dálki.
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>
Þetta gagnasafn skráir aðeins upplýsingar þegar fiskur hefur greinst í stöðinni, þ.e. ef einhver fiskur var ekki skráður af einhverri stöð, þá verða þessi gögn ekki í töflunni. Þetta þýðir að úttakið verður fyllt með NA.
Hins vegar í þessu tilfelli vitum við að skortur á skrá þýðir að fiskurinn sást ekki, svo við getum notað rökin values_fill í virkni pivot_wider() og fylltu þessi gildi sem vantar með núllum:
Ímyndaðu þér að við höfum töflu sem inniheldur blöndu af vöru, landi og ári. Til að búa til prufudagaramma geturðu keyrt eftirfarandi kóða:
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
Verkefni okkar er að stækka gagnarammann þannig að einn dálkur inniheldur gögn fyrir hverja samsetningu vöru og lands. Til að gera þetta, sendu bara rökin nöfn_frá vektor sem inniheldur nöfn reitanna sem á að sameina.
Þú getur líka beitt forskriftum fyrir aðgerð pivot_wider(). En þegar lögð var fram till pivot_wider() forskriftin gerir hið gagnstæða umbreytingu pivot_longer(): Dálkarnir sem tilgreindir eru í . Nafn, með því að nota gildi frá .gildi og öðrum dálkum.
Fyrir þetta gagnasafn geturðu búið til sérsniðna forskrift ef þú vilt að öll möguleg lönd og vörusamsetningar hafi sinn eigin dálk, ekki bara þær sem eru til staðar í gögnunum:
#> # 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
Nokkur háþróuð dæmi um að vinna með nýju tidyr hugmyndinni
Að hreinsa upp gögn með því að nota US Census Income and Rent gagnapakka sem dæmi.
Gagnasett okkur_leigutekjur inniheldur miðgildi tekna og leiguupplýsingar fyrir hvert ríki í Bandaríkjunum fyrir árið 2017 (gagnasett tiltækt í pakka tímatal).
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
Í því formi sem gögnin eru geymd í gagnasafninu okkur_leigutekjur að vinna með þeim er afar óþægilegt, svo við viljum búa til gagnasett með dálkum: leigja, leigja_moe, Komið, tekju_moe. Það eru margar leiðir til að búa til þessa forskrift, en aðalatriðið er að við þurfum að búa til hverja samsetningu af breytilegum gildum og áætla/moeog búðu til dálknafnið.
Stundum þarf nokkur skref að koma gagnasetti í æskilegt form.
Gagnasett heimsbankapopp inniheldur gögn Alþjóðabankans um íbúa hvers lands milli 2000 og 2018.
Markmið okkar er að búa til snyrtilegt gagnasafn með hverri breytu í sínum dálki. Það er óljóst nákvæmlega hvaða skref eru nauðsynleg, en við byrjum á augljósasta vandamálinu: árið er dreift yfir marga dálka.
Til að laga þetta þarftu að nota aðgerðina pivot_longer().
Næsta skref er að skoða vísisbreytuna. 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
Þar sem SP.POP.GROW er fólksfjölgun, SP.POP.TOTL er heildarfjöldi og SP.URB. * það sama, en aðeins fyrir þéttbýli. Við skulum skipta þessum gildum í tvær breytur: svæði - flatarmál (heildar eða þéttbýli) og breytu sem inniheldur raunveruleg gögn (íbúafjöldi eða vöxtur):
Það er frekar erfitt að setja þennan lista í töflu því það er engin breyta sem auðkennir hvaða gögn tilheyra hvaða tengilið. Við getum lagað þetta með því að hafa í huga að gögnin fyrir hvern nýjan tengilið byrja á „nafni“, svo við getum búið til einstakt auðkenni og aukið það um eitt í hvert skipti sem reitsdálkurinn inniheldur gildið „nafn“:
#> # 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
Nú þegar við höfum einstakt auðkenni fyrir hvern tengilið, getum við breytt reitnum og gildinu í dálka:
#> # 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>
Ályktun
Mín persónulega skoðun er sú að nýja hugtakið snyrtilegt sannarlega leiðandi og verulega betri í virkni en eldri aðgerðir spread() и gather(). Ég vona að þessi grein hafi hjálpað þér að takast á við pivot_longer() и pivot_wider().