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.

R-pakett tidyr ja selle uued funktsioonid pivot_longer ja pivot_wider

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.

TidyData kontseptsioon

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 korrastatud 0.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.

R-pakett tidyr ja selle uued funktsioonid pivot_longer ja pivot_wider

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.

R-pakett tidyr ja selle uued funktsioonid pivot_longer ja pivot_wider

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:

#> # A tibble: 18 x 11
#>    religion `<$10k` `$10-20k` `$20-30k` `$30-40k` `$40-50k` `$50-75k`
#>    <chr>      <dbl>     <dbl>     <dbl>     <dbl>     <dbl>     <dbl>
#>  1 Agnostic      27        34        60        81        76       137
#>  2 Atheist       12        27        37        52        35        70
#>  3 Buddhist      27        21        30        34        33        58
#>  4 Catholic     418       617       732       670       638      1116
#>  5 Don’t k…      15        14        15        11        10        35
#>  6 Evangel…     575       869      1064       982       881      1486
#>  7 Hindu          1         9         7         9        11        34
#>  8 Histori…     228       244       236       238       197       223
#>  9 Jehovah…      20        27        24        24        21        30
#> 10 Jewish        19        19        25        25        30        95
#> # … with 8 more rows, and 4 more variables: `$75-100k` <dbl>,
#> #   `$100-150k` <dbl>, `>150k` <dbl>, `Don't know/refused` <dbl>

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():

pew %>% 
  pivot_longer(cols = -religion, names_to = "income", values_to = "count")

pew %>% 
  pivot_longer(cols = -religion, names_to = "income", values_to = "count")
#> # A tibble: 180 x 3
#>    religion income             count
#>    <chr>    <chr>              <dbl>
#>  1 Agnostic <$10k                 27
#>  2 Agnostic $10-20k               34
#>  3 Agnostic $20-30k               60
#>  4 Agnostic $30-40k               81
#>  5 Agnostic $40-50k               76
#>  6 Agnostic $50-75k              137
#>  7 Agnostic $75-100k             122
#>  8 Agnostic $100-150k            109
#>  9 Agnostic >150k                 84
#> 10 Agnostic Don't know/refused    96
#> # … with 170 more rows

Funktsiooni argumendid 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")

#> # A tibble: 56 x 3
#>    .name        .value name        
#>    <chr>        <chr>  <chr>       
#>  1 new_sp_m014  count  new_sp_m014 
#>  2 new_sp_m1524 count  new_sp_m1524
#>  3 new_sp_m2534 count  new_sp_m2534
#>  4 new_sp_m3544 count  new_sp_m3544
#>  5 new_sp_m4554 count  new_sp_m4554
#>  6 new_sp_m5564 count  new_sp_m5564
#>  7 new_sp_m65   count  new_sp_m65  
#>  8 new_sp_f014  count  new_sp_f014 
#>  9 new_sp_f1524 count  new_sp_f1524
#> 10 new_sp_f2534 count  new_sp_f2534
#> # … with 46 more rows

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.
  • m/f patsiendi sugu.
  • 014/1524/2535/3544/4554/65 patsiendi vanusevahemik.

Funktsiooni abil saame need veerud jagada extract()kasutades regulaaravaldist.

spec <- spec %>%
        extract(name, c("diagnosis", "gender", "age"), "new_?(.*)_(.)(.*)")

#> # A tibble: 56 x 5
#>    .name        .value diagnosis gender age  
#>    <chr>        <chr>  <chr>     <chr>  <chr>
#>  1 new_sp_m014  count  sp        m      014  
#>  2 new_sp_m1524 count  sp        m      1524 
#>  3 new_sp_m2534 count  sp        m      2534 
#>  4 new_sp_m3544 count  sp        m      3544 
#>  5 new_sp_m4554 count  sp        m      4554 
#>  6 new_sp_m5564 count  sp        m      5564 
#>  7 new_sp_m65   count  sp        m      65   
#>  8 new_sp_f014  count  sp        f      014  
#>  9 new_sp_f1524 count  sp        f      1524 
#> 10 new_sp_f2534 count  sp        f      2534 
#> # … with 46 more rows

Pange tähele veergu . Nimi peaks jääma muutumatuks, kuna see on meie indeks algse andmekogumi veergude nimedesse.

Sugu ja vanus (veerud sugu и vanus) on fikseeritud ja teadaolevate väärtustega, seega on soovitatav need veerud teisendada teguriteks:

spec <-  spec %>%
            mutate(
              gender = factor(gender, levels = c("f", "m")),
              age = factor(age, levels = unique(age), ordered = TRUE)
            ) 

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:

R-pakett tidyr ja selle uued funktsioonid pivot_longer ja pivot_wider

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.

Loome treeningu andmeraami.

family <- tibble::tribble(
  ~family,  ~dob_child1,  ~dob_child2, ~gender_child1, ~gender_child2,
       1L, "1998-11-26", "2000-01-29",             1L,             2L,
       2L, "1996-06-22",           NA,             2L,             NA,
       3L, "2002-07-11", "2004-04-05",             2L,             2L,
       4L, "2004-10-10", "2009-08-27",             1L,             1L,
       5L, "2000-12-05", "2005-02-28",             2L,             1L,
)
family <- family %>% mutate_at(vars(starts_with("dob")), parse_date)

#> # A tibble: 5 x 5
#>   family dob_child1 dob_child2 gender_child1 gender_child2
#>    <int> <date>     <date>             <int>         <int>
#> 1      1 1998-11-26 2000-01-29             1             2
#> 2      2 1996-06-22 NA                     2            NA
#> 3      3 2002-07-11 2004-04-05             2             2
#> 4      4 2004-10-10 2009-08-27             1             1
#> 5      5 2000-12-05 2005-02-28             2             1

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.

family %>% 
    pivot_longer(spec = spec, na.rm = T)

#> # A tibble: 9 x 4
#>   family child dob        gender
#>    <int> <dbl> <date>      <int>
#> 1      1     1 1998-11-26      1
#> 2      1     2 2000-01-29      2
#> 3      2     1 1996-06-22      2
#> 4      3     1 2002-07-11      2
#> 5      3     2 2004-04-05      2
#> 6      4     1 2004-10-10      1
#> 7      4     2 2009-08-27      1
#> 8      5     1 2000-12-05      2
#> 9      5     2 2005-02-28      1

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.

R-pakett tidyr ja selle uued funktsioonid pivot_longer ja pivot_wider

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)

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:

fish_encounters %>% pivot_wider(
  names_from = station, 
  values_from = seen,
  values_fill = list(seen = 0)
)

#> # 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     0     0     0     0     0
#>  5 4847        1     1      1     0       0     0     0     0     0     0
#>  6 4848        1     1      1     1       0     0     0     0     0     0
#>  7 4849        1     1      0     0       0     0     0     0     0     0
#>  8 4850        1     1      0     1       1     1     1     0     0     0
#>  9 4851        1     1      0     0       0     0     0     0     0     0
#> 10 4854        1     1      0     0       0     0     0     0     0     0
#> # … with 9 more rows, and 1 more variable: MAW <int>

Veeru nime genereerimine mitmest lähtemuutujast

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.

df %>% pivot_wider(names_from = c(product, country),
                 values_from = "value")

#> # A tibble: 15 x 4
#>     year     A_AI    B_AI    B_EI
#>    <int>    <dbl>   <dbl>   <dbl>
#>  1  2000 -2.05     0.607   1.20  
#>  2  2001 -0.676    1.65   -0.114 
#>  3  2002  1.60    -0.0245  0.501 
#>  4  2003 -0.353    1.30   -0.459 
#>  5  2004 -0.00530  0.921  -0.0589
#>  6  2005  0.442   -1.55    0.594 
#>  7  2006 -0.610    0.380  -1.28  
#>  8  2007 -2.77     0.830   0.637 
#>  9  2008  0.899    0.0175 -1.30  
#> 10  2009 -0.106   -0.195   1.03  
#> # … with 5 more rows

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.

spec <- df %>% 
  expand(product, country, .value = "value") %>% 
  unite(".name", product, country, remove = FALSE)

#> # 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.

  spec <- us_rent_income %>% 
    expand(variable, .value = c("estimate", "moe")) %>% 
    mutate(
      .name = paste0(variable, ifelse(.value == "moe", "_moe", ""))
    )

#> # A tibble: 4 x 3
#>   variable .value   .name     
#>   <chr>    <chr>    <chr>     
#> 1 income   estimate income    
#> 2 income   moe      income_moe
#> 3 rent     estimate rent      
#> 4 rent     moe      rent_moe

Selle spetsifikatsiooni esitamine pivot_wider() annab meile soovitud tulemuse:

us_rent_income %>% pivot_wider(spec = spec)

#> # A tibble: 52 x 6
#>    GEOID NAME                 income income_moe  rent rent_moe
#>    <chr> <chr>                 <dbl>      <dbl> <dbl>    <dbl>
#>  1 01    Alabama               24476        136   747        3
#>  2 02    Alaska                32940        508  1200       13
#>  3 04    Arizona               27517        148   972        4
#>  4 05    Arkansas              23789        165   709        5
#>  5 06    California            29454        109  1358        3
#>  6 08    Colorado              32401        109  1125        5
#>  7 09    Connecticut           35326        195  1123        5
#>  8 10    Delaware              31560        247  1076       10
#>  9 11    District of Columbia  43198        681  1424       17
#> 10 12    Florida               25952         70  1077        3
#> # … with 42 more rows

Maailmapank

Mõnikord nõuab andmekogumi soovitud vormi viimine mitut sammu.
Andmekogum world_bank_pop sisaldab Maailmapanga andmeid iga riigi rahvaarvu kohta aastatel 2000–2018.

#> # A tibble: 1,056 x 20
#>    country indicator `2000` `2001` `2002` `2003`  `2004`  `2005`   `2006`
#>    <chr>   <chr>      <dbl>  <dbl>  <dbl>  <dbl>   <dbl>   <dbl>    <dbl>
#>  1 ABW     SP.URB.T… 4.24e4 4.30e4 4.37e4 4.42e4 4.47e+4 4.49e+4  4.49e+4
#>  2 ABW     SP.URB.G… 1.18e0 1.41e0 1.43e0 1.31e0 9.51e-1 4.91e-1 -1.78e-2
#>  3 ABW     SP.POP.T… 9.09e4 9.29e4 9.50e4 9.70e4 9.87e+4 1.00e+5  1.01e+5
#>  4 ABW     SP.POP.G… 2.06e0 2.23e0 2.23e0 2.11e0 1.76e+0 1.30e+0  7.98e-1
#>  5 AFG     SP.URB.T… 4.44e6 4.65e6 4.89e6 5.16e6 5.43e+6 5.69e+6  5.93e+6
#>  6 AFG     SP.URB.G… 3.91e0 4.66e0 5.13e0 5.23e0 5.12e+0 4.77e+0  4.12e+0
#>  7 AFG     SP.POP.T… 2.01e7 2.10e7 2.20e7 2.31e7 2.41e+7 2.51e+7  2.59e+7
#>  8 AFG     SP.POP.G… 3.49e0 4.25e0 4.72e0 4.82e0 4.47e+0 3.87e+0  3.23e+0
#>  9 AGO     SP.URB.T… 8.23e6 8.71e6 9.22e6 9.77e6 1.03e+7 1.09e+7  1.15e+7
#> 10 AGO     SP.URB.G… 5.44e0 5.59e0 5.70e0 5.76e0 5.75e+0 5.69e+0  4.92e+0
#> # … with 1,046 more rows, and 11 more variables: `2007` <dbl>,
#> #   `2008` <dbl>, `2009` <dbl>, `2010` <dbl>, `2011` <dbl>, `2012` <dbl>,
#> #   `2013` <dbl>, `2014` <dbl>, `2015` <dbl>, `2016` <dbl>, `2017` <dbl>

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().

pop2 <- world_bank_pop %>% 
  pivot_longer(`2000`:`2017`, names_to = "year")

#> # A tibble: 19,008 x 4
#>    country indicator   year  value
#>    <chr>   <chr>       <chr> <dbl>
#>  1 ABW     SP.URB.TOTL 2000  42444
#>  2 ABW     SP.URB.TOTL 2001  43048
#>  3 ABW     SP.URB.TOTL 2002  43670
#>  4 ABW     SP.URB.TOTL 2003  44246
#>  5 ABW     SP.URB.TOTL 2004  44669
#>  6 ABW     SP.URB.TOTL 2005  44889
#>  7 ABW     SP.URB.TOTL 2006  44881
#>  8 ABW     SP.URB.TOTL 2007  44686
#>  9 ABW     SP.URB.TOTL 2008  44375
#> 10 ABW     SP.URB.TOTL 2009  44052
#> # … with 18,998 more rows

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):

pop3 <- pop2 %>% 
  separate(indicator, c(NA, "area", "variable"))

#> # A tibble: 19,008 x 5
#>    country area  variable year  value
#>    <chr>   <chr> <chr>    <chr> <dbl>
#>  1 ABW     URB   TOTL     2000  42444
#>  2 ABW     URB   TOTL     2001  43048
#>  3 ABW     URB   TOTL     2002  43670
#>  4 ABW     URB   TOTL     2003  44246
#>  5 ABW     URB   TOTL     2004  44669
#>  6 ABW     URB   TOTL     2005  44889
#>  7 ABW     URB   TOTL     2006  44881
#>  8 ABW     URB   TOTL     2007  44686
#>  9 ABW     URB   TOTL     2008  44375
#> 10 ABW     URB   TOTL     2009  44052
#> # … with 18,998 more rows

Nüüd peame ainult jagama muutuja kahte veergu:

pop3 %>% 
  pivot_wider(names_from = variable, values_from = value)

#> # A tibble: 9,504 x 5
#>    country area  year   TOTL    GROW
#>    <chr>   <chr> <chr> <dbl>   <dbl>
#>  1 ABW     URB   2000  42444  1.18  
#>  2 ABW     URB   2001  43048  1.41  
#>  3 ABW     URB   2002  43670  1.43  
#>  4 ABW     URB   2003  44246  1.31  
#>  5 ABW     URB   2004  44669  0.951 
#>  6 ABW     URB   2005  44889  0.491 
#>  7 ABW     URB   2006  44881 -0.0178
#>  8 ABW     URB   2007  44686 -0.435 
#>  9 ABW     URB   2008  44375 -0.698 
#> 10 ABW     URB   2009  44052 -0.731 
#> # … with 9,494 more rows

Kontaktide nimekiri

Viimane näide, kujutage ette, et teil on kontaktide loend, mille kopeerisite ja kleepisite veebisaidilt:

contacts <- tribble(
  ~field, ~value,
  "name", "Jiena McLellan",
  "company", "Toyota", 
  "name", "John Smith", 
  "company", "google", 
  "email", "[email protected]",
  "name", "Huxley Ratcliffe"
)

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":

contacts <- contacts %>% 
  mutate(
    person_id = cumsum(field == "name")
  )
contacts

#> # 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:

contacts %>% 
  pivot_wider(names_from = field, values_from = value)

#> # 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().

Allikas: www.habr.com

Lisa kommentaar