R-paketti tidyr ja sen uudet toiminnot pivot_longer ja pivot_wider

paketti tidyr sisältyy yhden R-kielen suosituimman kirjaston ytimeen - siistiä.
Paketin päätarkoituksena on saattaa tiedot oikeaan muotoon.

Saatavilla jo Habrelta julkaisu omistettu tälle paketille, mutta se on peräisin vuodelta 2015. Ja haluan kertoa teille uusimmista muutoksista, joista sen kirjoittaja Hedley Wickham ilmoitti muutama päivä sitten.

R-paketti tidyr ja sen uudet toiminnot pivot_longer ja pivot_wider

SJK: Poistetaanko collect() and spread() käytöstä?

Hadley Wickham: Jossain määrin. Emme enää suosittele näiden toimintojen käyttöä ja korjaamaan niissä olevia bugeja, mutta ne ovat edelleen mukana paketissa nykyisessä tilassaan.

Pitoisuus

Jos olet kiinnostunut data-analyysistä, saatat olla kiinnostunut minun sähke и youtube kanavia. Suurin osa sisällöstä on omistettu R-kielelle.

TidyData-konsepti

Tavoite tidyr — auttaa saamaan tiedot niin sanottuun siistimuotoon. Puhtaat tiedot ovat tietoja, joissa:

  • Jokainen muuttuja on sarakkeessa.
  • Jokainen havainto on merkkijono.
  • Jokainen arvo on solu.

On paljon helpompaa ja mukavampaa työskennellä tietojen kanssa, jotka esitetään siisteissä tiedoissa analyysiä suoritettaessa.

Tidyr-paketin päätoiminnot

tidyr sisältää joukon toimintoja, jotka on suunniteltu muuttamaan taulukoita:

  • fill() — sarakkeen puuttuvien arvojen täyttäminen aikaisemmilla arvoilla;
  • separate() — jakaa yhden kentän useiksi erottimen avulla;
  • unite() — suorittaa useiden kenttien yhdistämistoiminnon yhdeksi, funktion käänteinen toiminta separate();
  • pivot_longer() — toiminto, joka muuntaa tiedot laajamuodosta pitkäksi;
  • pivot_wider() - toiminto, joka muuntaa tiedot pitkästä formaatista laajamuotoon. Käänteinen toiminto toiminnon suorittamasta operaatiosta pivot_longer().
  • gather()vanhentunut — toiminto, joka muuntaa tiedot laajamuodosta pitkäksi;
  • spread()vanhentunut - toiminto, joka muuntaa tiedot pitkästä formaatista laajamuotoon. Käänteinen toiminto toiminnon suorittamasta operaatiosta gather().

Uusi konsepti tietojen muuntamiseen leveästä pitkiin ja päinvastoin

Aikaisemmin funktioita käytettiin tällaiseen muunnokseen gather() и spread(). Näiden toimintojen olemassaolon vuosien aikana kävi selväksi, että useimmille käyttäjille, mukaan lukien paketin kirjoittaja, näiden funktioiden nimet ja niiden argumentit eivät olleet aivan ilmeisiä, mikä vaikeutti niiden löytämistä ja ymmärrystä, mikä näistä toiminnoista muuntaa. päivämääräkehyksen leveästä pitkiin ja päinvastoin.

Tässä suhteessa sisään tidyr Kaksi uutta, tärkeää toimintoa on lisätty, jotka on suunniteltu muuttamaan päivämääräkehyksiä.

Uudet ominaisuudet pivot_longer() и pivot_wider() sai inspiraationsa joistakin pakkauksen ominaisuuksista cdata, jonka ovat luoneet John Mount ja Nina Zumel.

Asennetaan uusin versio tidyr 0.8.3.9000

Asenna paketin uusi, viimeisin versio tidyr 0.8.3.9000, jos uusia ominaisuuksia on saatavilla, käytä seuraavaa koodia.

devtools::install_github("tidyverse/tidyr")

Kirjoitushetkellä nämä toiminnot ovat saatavilla vain paketin kehittäjäversiossa GitHubissa.

Siirtyminen uusiin ominaisuuksiin

Itse asiassa ei ole vaikeaa siirtää vanhoja komentosarjoja toimimaan uusien funktioiden kanssa, paremman ymmärtämisen vuoksi otan esimerkin vanhojen funktioiden dokumentaatiosta ja näytän kuinka samat toiminnot suoritetaan uusilla pivot_*() toimintoja.

Muunna laajakuva pitkäksi.

Esimerkkikoodi keräysfunktion dokumentaatiosta

# 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")

Pitkän muodon muuntaminen laajamuotoiseksi.

Esimerkkikoodi hajafunktion dokumentaatiosta

# old
stocks_spread <- stocks_gather %>% spread(key = stock, 
                                          value = price) 

# new 
stock_wide    <- stocks_long %>% pivot_wider(names_from  = "stock",
                                            values_from = "price")

Koska yllä olevissa esimerkeissä pivot_longer() и pivot_wider(), alkuperäisessä taulukossa osakkeet argumenteissa ei ole sarakkeita names_to и arvot_kohteen heidän nimensä on oltava lainausmerkeissä.

Taulukko, jonka avulla saat helpoimmin selville, kuinka voit siirtyä työskentelemään uuden konseptin parissa tidyr.

R-paketti tidyr ja sen uudet toiminnot pivot_longer ja pivot_wider

Huomautus kirjoittajalta

Kaikki alla oleva teksti on mukautuvaa, sanoisin jopa vapaata käännöstä vinjettejä tidyverse-kirjaston viralliselta verkkosivustolta.

Yksinkertainen esimerkki tietojen muuntamisesta laajasta muotoon pitkäksi

pivot_longer () — pidentää tietojoukkoja vähentämällä sarakkeiden määrää ja lisäämällä rivien määrää.

R-paketti tidyr ja sen uudet toiminnot pivot_longer ja pivot_wider

Artikkelissa esitettyjen esimerkkien suorittamiseksi sinun on ensin yhdistettävä tarvittavat paketit:

library(tidyr)
library(dplyr)
library(readr)

Oletetaan, että meillä on taulukko, jossa on tulokset kyselystä, jossa (muun muassa) kysyttiin ihmisiltä heidän uskontoaan ja vuositulojaan:

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

Tämä taulukko sisältää vastaajien uskontotiedot riveinä ja tulotasot on hajallaan sarakkeiden nimissä. Vastaajien lukumäärä kustakin kategoriasta on tallennettu soluarvoihin uskonnon ja tulotason leikkauspisteessä. Jotta taulukko saadaan siistiin, oikeaan muotoon, riittää käyttöä 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

Toiminnan argumentit pivot_longer()

  • Ensimmäinen argumentti kaulukset, kuvaa, mitkä sarakkeet on yhdistettävä. Tässä tapauksessa kaikki sarakkeet paitsi aika.
  • perustelu names_to antaa sen muuttujan nimen, joka luodaan ketjutettujen sarakkeiden nimistä.
  • arvot_kohteen antaa nimen muuttujalle, joka luodaan yhdistettyjen sarakkeiden solujen arvoihin tallennetuista tiedoista.

Tekniset tiedot

Tämä on paketin uusi toiminto tidyr, joka ei ollut aiemmin käytettävissä vanhojen toimintojen kanssa työskennellessä.

Määrittely on tietokehys, jonka jokainen rivi vastaa yhtä saraketta uudessa tulostuspäivämääräkehyksessä ja kahta erikoissaraketta, jotka alkavat seuraavasti:

  • . Nimi sisältää alkuperäisen sarakkeen nimen.
  • .arvo sisältää soluarvot sisältävän sarakkeen nimen.

Muut määritysten sarakkeet kertovat, kuinka uusi sarake näyttää pakattujen sarakkeiden nimet . Nimi.

Spesifikaatiossa kuvataan sarakkeen nimeen tallennetut metatiedot, yksi rivi kullekin sarakkeelle ja yksi sarake kullekin muuttujalle yhdistettynä sarakkeen nimeen, tämä määritelmä saattaa tällä hetkellä tuntua hämmentävältä, mutta muutaman esimerkin tarkastelun jälkeen siitä tulee paljon selkeämpi.

Määrityksen tarkoitus on, että voit hakea, muokata ja määrittää uusia metatietoja muunnettavalle tietokehykselle.

Käytä toimintoa, jos haluat työskennellä teknisten tietojen kanssa, kun muunnat taulukon laajasta muodosta pitkäksi pivot_longer_spec().

Tämä toiminto toimii siten, että se ottaa minkä tahansa päivämääräkehyksen ja luo sen metatiedot yllä kuvatulla tavalla.

Otetaan esimerkkinä paketin mukana toimitettu who-tietojoukko tidyr. Tämä aineisto sisältää kansainvälisen terveysjärjestön toimittamia tietoja tuberkuloosin esiintyvyydestä.

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

Rakennetaan sen spesifikaatio.

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

kentät maa, isoxnumx, isoxnumx ovat jo muuttujia. Tehtävämme on kääntää sarakkeita new_sp_m014 päälle newrel_f65.

Näiden sarakkeiden nimet sisältävät seuraavat tiedot:

  • etuliite new_ osoittaa, että sarake sisältää tietoja uusista tuberkuloositapauksista, nykyinen päivämääräkehys sisältää tiedot vain uusista sairauksista, joten tällä etuliitteellä ei ole nykyisessä kontekstissa mitään merkitystä.
  • sp/rel/sp/ep kuvailee menetelmän sairauden diagnosoimiseksi.
  • m/f potilaan sukupuoli.
  • 014/1524/2535/3544/4554/65 potilaan ikäluokka.

Voimme jakaa nämä sarakkeet funktiolla extract()käyttämällä säännöllistä lauseketta.

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

Huomioi sarake . Nimi pitäisi pysyä ennallaan, koska tämä on hakemistomme alkuperäisen tietojoukon sarakkeiden nimiin.

Sukupuoli ja ikä (sarakkeet sukupuoli и ikä) joilla on kiinteät ja tunnetut arvot, joten on suositeltavaa muuntaa nämä sarakkeet tekijöiksi:

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

Lopuksi, jotta voimme soveltaa luomaamme määritystä alkuperäiseen päivämääräkehykseen joka meidän on käytettävä argumenttia tekniset tiedot toiminnassa 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

Kaikki, mitä juuri teimme, voidaan kuvata kaavamaisesti seuraavasti:

R-paketti tidyr ja sen uudet toiminnot pivot_longer ja pivot_wider

Määrittely käyttämällä useita arvoja (.value)

Yllä olevassa esimerkissä määrityssarake .arvo sisälsi vain yhden arvon, useimmissa tapauksissa näin on.

Joskus voi kuitenkin syntyä tilanne, jossa sinun on kerättävä tietoja sarakkeista, joiden arvot ovat eri tietotyyppejä. Vanhan toiminnon käyttäminen spread() tämä olisi aika vaikea tehdä.

Alla oleva esimerkki on otettu vinjettejä pakettiin data. taulukko.

Luodaan harjoitustietokehys.

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

Luotu päivämääräkehys sisältää tiedot yhden perheen lapsista kullakin rivillä. Perheissä voi olla yksi tai kaksi lasta. Jokaisesta lapsesta ilmoitetaan syntymäaika ja sukupuoli, ja jokaisen lapsen tiedot ovat erillisissä sarakkeissa, meidän tehtävämme on saattaa tiedot oikeaan muotoon analysoitavaksi.

Huomaa, että meillä on kaksi muuttujaa, jotka sisältävät tietoja jokaisesta lapsesta: heidän sukupuolensa ja syntymäaikansa (sarakkeet etuliitteellä kaste sisältävät syntymäajan, sarakkeet etuliitteellä sukupuoli sisältää lapsen sukupuolen). Odotettu tulos on, että ne näkyvät erillisissä sarakkeissa. Voimme tehdä tämän luomalla eritelmän, jossa sarake .value on kaksi eri merkitystä.

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

Katsotaanpa siis vaiheittain yllä olevan koodin suorittamia toimia.

  • pivot_longer_spec(-family) — Luo määritys, joka pakkaa kaikki olemassa olevat sarakkeet perhesaraketta lukuun ottamatta.
  • separate(col = name, into = c(".value", "child")) - jakaa sarake . Nimi, joka sisältää lähdekenttien nimet käyttäen alaviivaa ja syöttämällä tuloksena saadut arvot sarakkeisiin .arvo и lapsi.
  • mutate(child = parse_number(child)) — muuntaa kentän arvot lapsi tekstistä numeeriseen tietotyyppiin.

Nyt voimme soveltaa tuloksena saatua määritystä alkuperäiseen tietokehykseen ja viedä taulukon haluttuun muotoon.

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

Käytämme argumenttia na.rm = TRUE, koska tietojen nykyinen muoto pakottaa luomaan ylimääräisiä rivejä olemattomille havainnoille. Koska perheessä 2 on vain yksi lapsi, na.rm = TRUE takaa, että perheessä 2 on yksi rivi tulosteessa.

Päivämääräkehysten muuntaminen pitkästä leveään muotoon

pivot_wider() - on käänteinen muunnos, ja päinvastoin lisää päivämääräkehyksen sarakkeiden määrää vähentämällä rivien määrää.

R-paketti tidyr ja sen uudet toiminnot pivot_longer ja pivot_wider

Tällaista muuntamista käytetään erittäin harvoin tietojen saattamiseksi oikeaan muotoon, mutta tämä tekniikka voi olla hyödyllinen esityksissä käytettävien pivot-taulukoiden luomisessa tai integroinnissa joihinkin muihin työkaluihin.

Itse asiassa toiminnot pivot_longer() и pivot_wider() ovat symmetrisiä ja tuottavat toisilleen käänteisiä toimia, eli: df %>% pivot_longer(spec = spec) %>% pivot_wider(spec = spec) и df %>% pivot_wider(spec = spec) %>% pivot_longer(spec = spec) palauttaa alkuperäisen df:n.

Yksinkertaisin esimerkki taulukon muuntamisesta laajaan muotoon

Osoittaaksesi, kuinka toiminto toimii pivot_wider() käytämme tietojoukkoa kala_kohtaamiset, joka tallentaa tietoa siitä, kuinka eri asemat tallentavat kalojen liikkumista joen varrella.

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

Useimmissa tapauksissa tämä taulukko on informatiivisempi ja helpompi käyttää, jos esität kunkin aseman tiedot erillisessä sarakkeessa.

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>

Tämä tietojoukko tallentaa tiedot vain, kun asema on havainnut kaloja, ts. jos jokin asema ei ole tallentanut kalaa, nämä tiedot eivät ole taulukossa. Tämä tarkoittaa, että ulostulo täytetään NA:lla.

Tässä tapauksessa tiedämme kuitenkin, että tietueen puuttuminen tarkoittaa, että kalaa ei nähty, joten voimme käyttää argumenttia arvot_täyttö toiminnassa pivot_wider() ja täytä nämä puuttuvat arvot nollilla:

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>

Sarakkeen nimen luominen useista lähdemuuttujista

Kuvittele, että meillä on taulukko, joka sisältää tuotteen, maan ja vuoden yhdistelmän. Voit luoda testipäivämääräkehyksen suorittamalla seuraavan koodin:

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

Tehtävämme on laajentaa tietokehystä niin, että yksi sarake sisältää tiedot jokaisesta tuotteen ja maan yhdistelmästä. Voit tehdä tämän välittämällä argumentin names_from vektori, joka sisältää yhdistettävien kenttien nimet.

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

Voit myös käyttää määrityksiä funktiolle pivot_wider(). Mutta kun annettiin pivot_wider() spesifikaatio tekee päinvastaisen muunnoksen pivot_longer(): kohdassa määritetyt sarakkeet . Nimi, käyttämällä arvoja alkaen .arvo ja muut sarakkeet.

Tälle tietojoukolle voit luoda mukautetun määrityksen, jos haluat, että jokaisella mahdollisella maa- ja tuoteyhdistelmällä on oma sarakensa, ei vain tiedoissa olevia:

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

Useita edistyneitä esimerkkejä työskentelystä uuden tidyr-konseptin kanssa

Tietojen puhdistaminen esimerkkinä Yhdysvaltain väestönlaskennan tulo- ja vuokratietojoukosta.

Tietojoukko meille_vuokratulot sisältää mediaanitulot ja vuokratiedot jokaisesta Yhdysvaltain osavaltiosta vuodelta 2017 (tietojoukko saatavilla pakkauksessa siisti väestönlaskenta).

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

Siinä muodossa, jossa tiedot on tallennettu tietojoukkoon meille_vuokratulot niiden kanssa työskentely on erittäin hankalaa, joten haluaisimme luoda tietojoukon, jossa on sarakkeita: Vuokrataan, vuokra_moe, Tulla, tulo_moe. On monia tapoja luoda tämä eritelmä, mutta pääasia on, että meidän on luotava jokainen muuttuja-arvojen ja arvio/moeja luo sitten sarakkeen 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

Toimittamalla tämä eritelmä pivot_wider() antaa meille etsimämme tuloksen:

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

Maailmanpankki

Joskus tietojoukon saattaminen haluttuun muotoon vaatii useita vaiheita.
Tietojoukko world_bank_pop Sisältää Maailmanpankin tiedot kunkin maan väestöstä vuosina 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>

Tavoitteenamme on luoda siisti tietojoukko, jossa jokainen muuttuja on omassa sarakkeessaan. On epäselvää, mitä toimia tarvitaan, mutta aloitamme ilmeisimmästä ongelmasta: vuosi on jaettu useisiin sarakkeisiin.

Tämän korjaamiseksi sinun on käytettävä toimintoa 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

Seuraava askel on tarkastella indikaattorimuuttujaa.
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

Missä SP.POP.GROW on väestönkasvu, SP.POP.TOTL on koko väestö ja SP.URB. * sama asia, mutta vain kaupunkialueilla. Jaetaan nämä arvot kahteen muuttujaan: alue - alue (koko tai kaupunki) ja muuttuja, joka sisältää todellisia tietoja (väestö tai kasvu):

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

Nyt meidän tarvitsee vain jakaa muuttuja kahteen sarakkeeseen:

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

Yhteystietoluettelo

Viimeinen esimerkki, kuvittele, että sinulla on yhteystietoluettelo, jonka kopioit ja liitit verkkosivustolta:

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

Tämän luettelon taulukoiminen on melko vaikeaa, koska siinä ei ole muuttujaa, joka tunnistaisi, mitkä tiedot kuuluvat millekin kontaktille. Voimme korjata tämän huomioimalla, että jokaisen uuden yhteyshenkilön tiedot alkavat sanalla "name", joten voimme luoda yksilöllisen tunnisteen ja kasvattaa sitä yhdellä aina, kun kenttäsarake sisältää arvon "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

Nyt kun meillä on yksilöllinen tunnus jokaiselle yhteyshenkilölle, voimme muuttaa kentän ja arvon sarakkeiksi:

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>

Johtopäätös

Henkilökohtainen mielipiteeni on, että uusi konsepti tidyr todella intuitiivisempi ja toiminnallisesti huomattavasti parempi kuin vanhat toiminnot spread() и gather(). Toivon, että tämä artikkeli auttoi sinua käsittelemään asiaa pivot_longer() и pivot_wider().

Lähde: will.com

Lisää kommentti