ProHoster > Blogi > Haldamine > R-pakett tidyr ja selle uued funktsioonid pivot_longer ja pivot_wider
R-pakett tidyr ja selle uued funktsioonid pivot_longer ja pivot_wider
Pakk korrastatud sisaldub ühe populaarseima R-keele raamatukogu tuumas - korrastatu.
Paketi põhieesmärk on viia andmed täpsele kujule.
Habré's juba saadaval väljaanne pühendatud sellele paketile, kuid see pärineb 2015. aastast. Ja ma tahan teile rääkida kõige värskematest muudatustest, millest mõni päev tagasi teatas selle autor Hedley Wickham.
SJK: Kas kogu() ja spread() tugi tühistatakse?
Hadley Wickham: Mingi piirini. Me ei soovita enam neid funktsioone kasutada ja neis vigu parandada, kuid need on praeguses olekus paketis jätkuvalt olemas.
Sisu
Kui olete huvitatud andmete analüüsist, võite olla huvitatud minu telegramm и youtube kanalid. Suurem osa sisust on pühendatud R-keelele.
Eesmärk korrastatud — aitavad andmed n-ö korralikule vormile viia. Puhtad andmed on andmed, kus:
Iga muutuja on veerus.
Iga vaatlus on string.
Iga väärtus on lahter.
Analüüsi tegemisel on palju lihtsam ja mugavam töötada andmetega, mis on esitatud korrastatud andmetena.
Tidyr paketis sisalduvad põhifunktsioonid
tidyr sisaldab tabelite teisendamiseks mõeldud funktsioonide komplekti:
fill() — veerus puuduvate väärtuste täitmine eelmiste väärtustega;
separate() — jagab ühe välja mitmeks eraldaja abil;
unite() — sooritab mitme välja üheks ühendamise operatsiooni, funktsiooni pöördtoimingu separate();
pivot_longer() — funktsioon, mis teisendab andmed laiformaadist pikaks;
pivot_wider() - funktsioon, mis teisendab andmed pikast vormingust laiformaadiks. Funktsiooni poolt sooritatava pöördtehing pivot_longer().
gather()aegunud — funktsioon, mis teisendab andmed laiformaadist pikaks;
spread()aegunud - funktsioon, mis teisendab andmed pikast vormingust laiformaadiks. Funktsiooni poolt sooritatava pöördtehing gather().
Uus kontseptsioon andmete teisendamiseks laiformaadist pikaks ja vastupidi
Varem kasutati seda tüüpi teisendamiseks funktsioone gather() и spread(). Nende funktsioonide eksisteerimise aastate jooksul sai selgeks, et enamiku kasutajate jaoks, sealhulgas paketi autori jaoks, ei olnud nende funktsioonide nimed ja argumendid päris selged ning tekitasid raskusi nende leidmisel ja mõistmisel, milline neist funktsioonidest teisendab. kuupäevaraami laiformaadist pika vorminguni ja vastupidi.
Sellega seoses in korrastatud Lisatud on kaks uut olulist funktsiooni, mis on mõeldud kuupäevaraamide muutmiseks.
Uued omadused pivot_longer() и pivot_wider() olid inspireeritud mõnest pakendi funktsioonist cdata, mille on loonud John Mount ja Nina Zumel.
Tidyr uusima versiooni 0.8.3.9000 installimine
Paketi uue, uusima versiooni installimiseks korrastatud0.8.3.9000, kus uued funktsioonid on saadaval, kasutage järgmist koodi.
devtools::install_github("tidyverse/tidyr")
Kirjutamise ajal olid need funktsioonid saadaval ainult GitHubi paketi arendajaversioonis.
Üleminek uutele funktsioonidele
Tegelikult pole vanade skriptide ülekandmine uute funktsioonidega töötamiseks keeruline, parema arusaamise huvides toon näite vanade funktsioonide dokumentatsioonist ja näitan, kuidas samu toiminguid tehakse uute funktsioonidega. pivot_*() funktsioonid.
Teisendage laiformaat pikaks vorminguks.
Näidiskood kogumisfunktsiooni dokumentatsioonist
# 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")
Pika formaadi teisendamine laiformaadiks.
Näidiskood levifunktsiooni dokumentatsioonist
# old
stocks_spread <- stocks_gather %>% spread(key = stock,
value = price)
# new
stock_wide <- stocks_long %>% pivot_wider(names_from = "stock",
values_from = "price")
Sest ülaltoodud näidetes töötamise kohta pivot_longer() и pivot_wider(), originaaltabelis varude argumentides pole ühtegi veergu nimed_ и väärtused_kuni nende nimed peavad olema jutumärkides.
Tabel, mis aitab teil kõige hõlpsamini aru saada, kuidas uue kontseptsiooniga tööle lülituda korrastatud.
Märkus autorilt
Kogu allolev tekst on adaptiivne, ma ütleks isegi, et vabatõlge vinjetid Tidyverse'i raamatukogu ametlikult veebisaidilt.
Lihtne näide andmete teisendamisest laiformaadist pikaks
pivot_longer () — muudab andmekogumid pikemaks, vähendades veergude arvu ja suurendades ridade arvu.
Artiklis esitatud näidete käivitamiseks peate esmalt ühendama vajalikud paketid:
library(tidyr)
library(dplyr)
library(readr)
Oletame, et meil on tabel uuringu tulemustega, kus (muu hulgas) küsiti inimestelt nende usutunnistuse ja aastasissetuleku kohta:
See tabel sisaldab ridade kaupa vastajate religiooniandmeid ja sissetulekutasemed on veergude nimede vahel hajutatud. Iga kategooria vastajate arv salvestatakse lahtri väärtustesse religiooni ja sissetuleku taseme ristumiskohas. Tabeli viimistlemiseks korralikku ja õigesse vormingusse piisab, kui kasutada pivot_longer():
Esimene argument kraed, kirjeldab, millised veerud tuleb liita. Sel juhul kõik veerud v.a aeg.
argument nimed_ annab muutuja nime, mis luuakse meie ühendatud veergude nimedest.
väärtused_kuni annab muutuja nime, mis luuakse ühendatud veergude lahtrite väärtustesse salvestatud andmetest.
Tehnilised nõuded
See on paketi uus funktsioon korrastatud, mis polnud varem pärandfunktsioonidega töötamisel saadaval.
Spetsifikatsioon on andmeraam, mille iga rida vastab ühele veerule uues väljundkuupäeva raamis ja kahele spetsiaalsele veerule, mis algavad järgmiselt:
. Nimi sisaldab algset veeru nime.
.väärtus sisaldab lahtri väärtusi sisaldava veeru nime.
Ülejäänud spetsifikatsiooni veerud kajastavad seda, kuidas uues veerus kuvatakse tihendatud veergude nimed . Nimi.
Spetsifikatsioon kirjeldab veeru nimes salvestatud metaandmeid, kus iga veeru jaoks on üks rida ja iga muutuja jaoks üks veerg, kombineerituna veeru nimega, see määratlus võib hetkel tunduda segane, kuid pärast mõne näite vaatamist muutub see paljuks. selgemaks.
Spetsifikatsiooni mõte on see, et saate teisendatava andmeraami jaoks hankida, muuta ja uusi metaandmeid määratleda.
Spetsifikatsioonidega töötamiseks tabeli laivormingust pikaks teisendamiseks kasutage funktsiooni pivot_longer_spec().
See funktsioon töötab nii, et see võtab mis tahes kuupäevaraami ja loob selle metaandmed ülalkirjeldatud viisil.
Näitena võtame paketiga kaasas oleva andmestiku kes korrastatud. See andmestik sisaldab teavet, mille on esitanud rahvusvaheline tervishoiuorganisatsioon tuberkuloosi esinemissageduse kohta.
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
Koostame selle spetsifikatsiooni.
spec <- who %>%
pivot_longer_spec(new_sp_m014:newrel_f65, values_to = "count")
väljad riik, isoxnumx, isoxnumx on juba muutujad. Meie ülesandeks on veergude ümberpööramine uus_sp_m014 edasi newrel_f65.
Nende veergude nimed salvestavad järgmise teabe:
Eesliide new_ näitab, et veerg sisaldab andmeid uute tuberkuloosijuhtude kohta, praegune kuupäevaraam sisaldab teavet ainult uute haiguste kohta, seega ei oma see eesliide praeguses kontekstis mingit tähendust.
sp/rel/sp/ep kirjeldab haiguse diagnoosimise meetodit.
Lõpuks, selleks, et rakendada meie loodud spetsifikatsiooni algsele kuupäevaraamile kes peame kasutama argumenti spec funktsioonis 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
Kõike, mida me just tegime, saab skemaatiliselt kujutada järgmiselt:
Spetsifikatsioon, kasutades mitut väärtust (.value)
Ülaltoodud näites spetsifikatsiooni veerg .väärtus sisaldas ainult ühte väärtust, enamikul juhtudel see nii on.
Kuid mõnikord võib tekkida olukord, kus peate koguma andmeid erinevat tüüpi väärtustega veergudest. Pärandfunktsiooni kasutamine spread() seda oleks päris raske teha.
Allolev näide on võetud vinjetid pakendile andmed.tabel.
Loodud kuupäevaraam sisaldab igal real andmeid ühe pere laste kohta. Peredel võib olla üks või kaks last. Iga lapse kohta esitatakse andmed sünnikuupäeva ja soo kohta ning iga lapse andmed on eraldi veergudes, meie ülesanne on viia need andmed analüüsimiseks õigesse vormingusse.
Pange tähele, et meil on kaks muutujat, mis sisaldavad teavet iga lapse kohta: nende sugu ja sünnikuupäev (veerud eesliitega Ristimine sisaldavad sünnikuupäeva, eesliitega veerge sugu sisaldama lapse sugu). Eeldatav tulemus on see, et need peaksid ilmuma eraldi veergudena. Seda saame teha, genereerides spetsifikatsiooni, milles veerg .value sellel on kaks erinevat tähendust.
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
Niisiis, vaatame samm-sammult ülaltoodud koodiga tehtud toiminguid.
pivot_longer_spec(-family) — luua spetsifikatsioon, mis tihendab kõik olemasolevad veerud peale perekonna veeru.
separate(col = name, into = c(".value", "child")) - jagage veerg . Nimi, mis sisaldab lähteväljade nimesid, kasutades allkriipsu ja sisestades saadud väärtused veergudesse .väärtus и laps.
mutate(child = parse_number(child)) — teisendada välja väärtused laps tekstist numbrilise andmetüübini.
Nüüd saame rakendada saadud spetsifikatsiooni algsele andmeraamile ja viia tabeli soovitud kujule.
Me kasutame argumente na.rm = TRUE, sest praegune andmete vorm sunnib olematute vaatluste jaoks lisaridu looma. Sest peres 2 on ainult üks laps, na.rm = TRUE garanteerib, et perekonnal 2 on väljundis üks rida.
Kuupäevaraamide teisendamine pikast laiformaadiks
pivot_wider() - on pöördteisendus ja vastupidi suurendab kuupäevaraami veergude arvu, vähendades ridade arvu.
Seda tüüpi teisendust kasutatakse andmete täpseks muutmiseks äärmiselt harva, kuid see tehnika võib olla kasulik esitlustes kasutatavate pivot-tabelite loomisel või mõne muu tööriistaga integreerimiseks.
Tegelikult funktsioonid pivot_longer() и pivot_wider() on sümmeetrilised ja tekitavad toiminguid üksteise suhtes vastupidiselt, st: df %>% pivot_longer(spec = spec) %>% pivot_wider(spec = spec) и df %>% pivot_wider(spec = spec) %>% pivot_longer(spec = spec) tagastab originaali df.
Lihtsaim näide tabeli teisendamiseks laiformaadiks
Funktsiooni toimimise demonstreerimiseks pivot_wider() kasutame andmestikku kala_kohtumised, mis salvestab teavet selle kohta, kuidas erinevad jaamad salvestavad kalade liikumist jõe ääres.
#> # 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
Enamikul juhtudel on see tabel informatiivsem ja hõlpsamini kasutatav, kui esitate teabe iga jaama kohta eraldi veerus.
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>
See andmekogum salvestab teavet ainult siis, kui jaam on kala tuvastanud, s.t. kui mõni jaam ei registreerinud mingit kala, siis neid andmeid tabelisse ei tule. See tähendab, et väljund täidetakse NA-ga.
Kuid antud juhul teame, et kirje puudumine tähendab, et kala ei nähtud, seega saame argumenti kasutada väärtused_täitmine funktsioonis pivot_wider() ja täitke need puuduvad väärtused nullidega:
Kujutage ette, et meil on tabel, mis sisaldab toote, riigi ja aasta kombinatsiooni. Testikuupäeva raami loomiseks saate käivitada järgmise koodi:
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
Meie ülesanne on laiendada andmeraami nii, et üks veerg sisaldaks andmeid iga toote ja riigi kombinatsiooni kohta. Selleks edastage lihtsalt argument nimed_kohast vektor, mis sisaldab liidetavate väljade nimesid.
Funktsioonile saate rakendada ka spetsifikatsioone pivot_wider(). Aga kui esitatakse pivot_wider() spetsifikatsioon teeb vastupidise teisenduse pivot_longer(): veerud, mis on määratud jaotises . Nimi, kasutades väärtusi alates .väärtus ja muud veerud.
Selle andmestiku jaoks saate luua kohandatud spetsifikatsiooni, kui soovite, et igal võimalikul riigil ja tootekombinatsioonil oleks oma veerg, mitte ainult need, mis on andmetes.
#> # 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
Mitmed täiustatud näited uue tidyr kontseptsiooniga töötamise kohta
Andmete puhastamine, kasutades näitena USA rahvaloenduse tulude ja rendiandmete kogumit.
Andmekogum meie_rent_tulu sisaldab mediaansissetuleku ja üüriteavet iga USA osariigi kohta 2017. aastal (andmed on saadaval pakendis korrasloendus).
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
Vormis, milles andmed andmekogumisse salvestatakse meie_rent_tulu nendega töötamine on äärmiselt ebamugav, seetõttu soovime luua veergudega andmekogumi: rent, rent_moe, Tulema, tulu_raha. Selle spetsifikatsiooni loomiseks on palju viise, kuid peamine on see, et peame genereerima kõik muutuvate väärtuste ja väärtuste kombinatsioonid. hinnang/moeja seejärel genereerige veeru nimi.
Mõnikord nõuab andmekogumi soovitud vormi viimine mitut sammu.
Andmekogum world_bank_pop sisaldab Maailmapanga andmeid iga riigi rahvaarvu kohta aastatel 2000–2018.
Meie eesmärk on luua korralik andmekogum, kus iga muutuja on oma veerus. On ebaselge, milliseid samme täpselt vaja on, kuid alustame kõige ilmsemast probleemist: aasta on jaotatud mitme veeru peale.
Selle parandamiseks peate kasutama funktsiooni pivot_longer().
Järgmine samm on indikaatori muutuja vaatamine. 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
Kui SP.POP.GROW on rahvastiku kasv, siis SP.POP.TOTL on kogurahvastik ja SP.URB. * sama asi, kuid ainult linnapiirkondade jaoks. Jagame need väärtused kaheks muutujaks: pindala - pindala (kogu või linnapiirkond) ja tegelikke andmeid sisaldav muutuja (rahvaarv või kasv):
Selle loendi tabeli koostamine on üsna keeruline, kuna puudub muutuja, mis tuvastaks, millised andmed millisele kontaktile kuuluvad. Saame seda parandada, pannes tähele, et iga uue kontakti andmed algavad sõnaga "name", nii et saame luua kordumatu identifikaatori ja suurendada seda ühe võrra iga kord, kui välja veerg sisaldab väärtust "nimi":
#> # 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üüd, kui meil on iga kontakti jaoks kordumatu ID, saame muuta välja ja väärtuse veergudeks:
#> # 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>
Järeldus
Minu isiklik arvamus on, et uus kontseptsioon korrastatud tõeliselt intuitiivsem ja funktsionaalsuselt märkimisväärselt parem kui pärandfunktsioonid spread() и gather(). Loodan, et see artikkel aitas teil sellega toime tulla pivot_longer() и pivot_wider().