Pakett tidyr kõigest üks populaarsemaid R keele teeke — tidyverse.
Pakkumise peamine eesmärk on andmete korrektne vormindamine.
Habras on juba olemas selle paketile, kuid see on dateeritud 2015. aastaga. Soovin rääkida kõige olulisematest muudatustest, millest paar päeva tagasi teatas selle looja Hadley Wickham.

SJK: Kas funktsioonid gather() ja spread() muutuvad aeglaseks?
Hadley Wickham: Teatud määral. Me lõpetame nende funktsioonide kasutamise soovitamise ja vigade parandamise, kuid need jäävad paketti senisel kujul.
Sisu
Kui teid huvitab andmeanalüüs, siis võivad teile huvi pakkuda minu ja kanalid. Suur osa sisust on pühendatud R keelele.
TidyData kontseptsioon
Eesmärk tidyr — aidata teil andmed viia nii nimetatud korrastatud vormi. Korrastatud andmed on andmed, kus:
- Iga muutuja asub veerus.
- Iga vaatlus on rida.
- Iga väärtus on lahtris.
Korrastatud andmetega on analüüsi teostamine oluliselt lihtsam ja mugavam.
Peamised funktsioonid, mis kuuluvad tidyr paketti
tidyr sisaldab funktsioonide kogumit, mis on mõeldud tabelite muutmiseks:
fill()— täidab puuduvad väärtused veerus eelnevate väärtustega;separate()— jagab ühe välja mitmeks, kasutades eraldajat;unite()— teostab mitme välja ühendamise üheks, vastandav tegevus funktsioonileseparate();pivot_longer()— funktsioon, mis muundab andmed laias vormingus pikaks;pivot_wider()— funktsioon, mis muundab andmed pikast vormingust laiaks. Tegevus on vastupidine funktsioonipivot_longer().gather()aegunud — funktsioon, mis muundab andmed laias vormingus pikaks;spread()aegunud — funktsioon, mis muundab andmed pikast vormingust laiaks. Tegevus on vastupidine funktsioonigather().
Uus kontseptsioon andmete teisendamisest laiast vormingust pika vorminguni ja vastupidi
Varem kasutati sarnaste transformatsioonide jaoks funktsioone gather() ja spread(). Aastate jooksul on nende funktsioonide kasutamise osas selgunud, et enamikule kasutajatest, sealhulgas paketi autorile, ei ole nende funktsioonide nimed ja argumendid olnud piisavalt selged, tekitades raskusi nende leidmisel ja mõistmisel, milline neist funktsioonidest muudab andmeframe laia formaadi pikkaks ja vastupidi.
Seetõttu tidyr on lisatud kaks uut, olulist funktsiooni, mis on mõeldud andmeframe'i muutmiseks.
Uued funktsioonid pivot_longer() ja pivot_wider() on loodud inspiratsiooni saades mõnest funktsioonist paketist cdata, mille on välja töötanud John Mount ja Nina Zumel.
Tidyr 0.8.3.9000 kõige värskema versiooni installimine
Uue, kõige värskema versiooni paigaldamiseks paketist tidyr 0.8.3.9000, kus on saadaval uued funktsioonid, kasutage järgmisi koodi.
devtools::install_github("tidyverse/tidyr")
Artikli kirjutamise hetkel on need funktsioonid saadaval ainult GitHubi dev versioonis paketist.
Uutele funktsioonidele üleminek
Tegelikult ei ole vanade skriptide uute funktsioonide kasutusele võtmine keeruline, et paremini mõista, toon näite vanade funktsioonide dokumentatsioonist ja näitan, kuidas samu toiminguid teostatakse uute pivot_*() funktsioonide abil.
Laiast formaadist pikaks muutmine.
Koodinäide funktsiooni gather 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")
Pikkforma muutmine laiaks.
Koodinäide spread funktsiooni dokumentatsioonist
# old
stocks_spread <- stocks_gather %>% spread(key = stock,
value = price)
# new
stock_wide <- stocks_long %>% pivot_wider(names_from = "stock",
values_from = "price")
Kuna ülaltoodud näidetes on töötamise osas pivot_longer() ja pivot_wider(), algses tabelis lisamine MSI-sse (uus struktuur) ei too kaasa uute kirjete tekke. ei ole tulpasid, mis on loetletud argumentides names_to ja values_to nende nimed tuleb panna jutumärkidesse.
Tabel, mille abil on teil kõige lihtsam aru saada, kuidas alustada uue kontseptsiooniga tidyr.

Autorilt märkus
Kõik edasine tekst on kohandatud, ma ütleksin, et vaba tõlge tidyverse'i ametlikult veebisaidilt.
Lihtne näide andmete teisendamisest laiast vormingust pika vorminguni
pivot_longer () — pikendab andmekogumeid, vähendades veergude arvu ja suurendades ridade arvu.

Käesolevas artiklis esitatud näidete täitmiseks tuleb esmalt lisada vajalikud paketid:
library(tidyr)
library(dplyr)
library(readr)Oletame, et meil on küsitlustulemustega tabel, kus (muuhulgas) küsiti inimesi nende usunde ja aastase sissetuleku 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 vastajate religiooniga seotud andmeid ridade kaupa, samas kui sissetuleku tase on jaotatud veergude nimetustes. Iga kategooria vastajate arv on talletatud lahtrite väärtustes, mis näitavad religiooni ja sissetuleku taset. Tabeli toomiseks korralikku, õiget 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
#>
#> 1 Agnostik <$10k 27
#> 2 Agnostik $10-20k 34
#> 3 Agnostik $20-30k 60
#> 4 Agnostik $30-40k 81
#> 5 Agnostik $40-50k 76
#> 6 Agnostik $50-75k 137
#> 7 Agnostik $75-100k 122
#> 8 Agnostik $100-150k 109
#> 9 Agnostik >150k 84
#> 10 Agnostik Ei tea/keeldus 96
#> # … kokku 170 rida rohkemFunktsiooni argumendid pivot_longer()
- Esimene argument cols, kirjeldab, millised veerud tuleb kokku liita. Antud juhul kõik veerud, välja arvatud aeg.
- Argument names_to annab nime muutujale, mis luuakse veergude nimedest, mida me kokku liitsime.
- values_to annab nime muutujale, mis luuakse andmetest, mis on talletatud lahtrite väärtustes kokku liidetud veergudest.
Spetsifikatsioonid
See on uus funktsionaalsus pakendis tidyr, mis oli varem vanade funktsioonide kasutamisel kättesaamatu.
Spetsifikatsioon on andmeraam, mille iga rida vastab uue väljundi data frame'i ühele veerule ja kahe eriveerule, mis algavad:
- .nimi sisaldab algset veeru nime.
- .value sisaldab veeru nime, kuhu väärtused sisestatakse.
Ülejäänud spetsifikatsiooni veerud peegeldavad, kuidas uues veerus kuvatakse tihendatud veergude nimed .nimi.
Spetsifikatsioon kirjeldab veeru nimesse salvestatud metaandmeid, iga veeru jaoks üks rida ja iga muutuja jaoks üks veerg, mis on ühendatud veeru nimega; praegu tundub see määratlemine võib-olla segane, kuid pärast mitme näite vaatamist saab kõik oluliselt selgemaks.
Spetsifikatsiooni mõte on see, et saate ekstrapoleerida, muuta ja määrata uusi metaandmeid muudetavasse data frame'i.
Spetsifikatsioonide töötlemiseks laua muutmisel laiast vormingust pikaks sobib funktsioon pivot_longer_spec().
Kuidas see funktsioon töötab, see võtab mistahes andmeraami ja koostab selle metaandmed ülaltoodud viisil.
Näiteks võtame andmestiku who, mis on saadaval koos paketiga. tidyr. See andmestik sisaldab teavet, mida pakub Maailma Terviseorganisatsioon tuberkuloosihaiguse kohta.
who
#> # A tibble: 7,240 x 60
#> country iso2 iso3 year new_sp_m014 new_sp_m1524 new_sp_m2534
#>
#> 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
#> # … koos 7,230 rohkem rea, ja 53 rohkem muutujatLoome selle spetsifikatsiooni.
spec %
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 rowsMuutujad country, iso2, iso3 on juba muutujad. Meie ülesanne on pöörata veergudega. new_sp_m014 kohta newrel_f65.
Selles veergu nimed sisaldavad järgmist teavet:
- Eesliide
new_näitab, et veerg sisaldab andmeid tuberkuloosi uutest juhtumitest; praegune andmeframe sisaldab teavet ainult uute juhtumite kohta, seega ei oma see prefiks antud kontekstis mingit tähenduslikku koormust. sp/rel/sp/epkirjeldab haiguse diagnoosimise viisi.m/fpatsiendi sugu.014/1524/2535/3544/4554/65patsiendi vanuserühm.
Saame neid veerge eraldada funktsiooni abil extract(), kasutades regulaaravatust.
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 rowsPange tähele, et veerg .nimi peaks jääma muutumatuks, kuna see on meie indeks veergude nimedes algses andmekogumis.
Sugu ja vanus (veergude gender ja age) omavad fikseeritud ja teadaolevaid väärtusi, seetõttu on soovitatav muuta need veerud faktoriteks:
spec %
mutate(
gender = factor(gender, levels = c("f", "m")),
age = factor(age, levels = unique(age), ordered = TRUE)
) Lõpuks, et rakendada loodud spetsifikatsiooni algsele andmeframe'ile who 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 rowsKogu see, mida me just tegime, võib visuaalselt kirjeldada järgmiselt:

Mitu väärtuse kasutamise spetsiifikatsioon (.value)
Ülaltoodud näites sisaldas spetsifikatsiooni veerg .value ainult ühte väärtust, mis on enamikul juhtudel tõsi.
Kuid harva võib tekkida olukord, kus peate koguma väärtustes andmeid erinevate andmetüüpidega veergudest. Aegunud funktsiooni abil spread() oli seda üsna keeruline teha.
Allolev näide on laenatud paketist data.table.
Loome treeningandmestiku.
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 % 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 1Loodud andmestik sisaldab igas reas andmeid ühe pere laste kohta. Peredes võib olla üks või kaks last. Iga lapse kohta esitatakse andmed sünnikuupäeva ja soo kohta, kusjuures andmed igasuguse lapse kohta asuvad eraldi veergudes, meie ülesanne on tuua need andmed analüüsimiseks õiges vormingus.
Pange tähele, et meil on iga lapse kohta kaks muutujat: tema sugu ja sünnikuupäev (veergude, mille eelnevad on dop sisaldavad sünnikuupäeva, veergude, mille eelnevad on gender sisaldavad lapse soo). Oodatavas tulemuses peavad need olema eraldi veergudes. Saame seda teha, genereerides spetsifikatsiooni, kus veerg .value oma kaht erinevat väärtust.
spec %
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 2Nii et vaatame samm-sammult läbi tegevused, mida ülaltoodud kood teeb.
pivot_longer_spec(-family)— loome spetsifikatsiooni, mis kokku surub kõik olemasolevad veerud, välja arvatud veerg family.separate(col = name, into = c(".value", "child"))— jagame veeru .nimi, mis sisaldab algsete väljade nimesid, allajoonimise järgi ja paneme saadud väärtused veergudesse. .value ja laps.mutate(child = parse_number(child))— muudetakse väli laps tekstist numbriväärtuseks.
Nüüd saame rakendada saadud spetsifikatsiooni algsele andmereale ja tuua tabeli soovitud vormi.
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 1Kasutame argumenti na.rm = TRUE, kuna praegune andmevorm sunnib looma ebavajalikke ridu mitteeksisteerivate vaatlustega. Kuna perel 2 on vaid üks laps, na.rm = TRUE tagab, et perel 2 on väljundandmetes vaid üks rida.
Andframe'ide teisendamine pikast vormingust laia vormingusse
pivot_wider() — on tagasimuundamine, ja vastupidi suurendab andmeraami veergude arvu ridu vähendades.

Sellist tüüpi muundamist kasutatakse äärmiselt harva andmete korralikuks vormistamiseks, kuid see tehnika võib olla kasulik koostöös aruande tabelite valmistamisel, mis on ette nähtud esitlusteks või integratsiooniks teiste tööriistadega.
Tegelikult on funktsioonid pivot_longer() ja pivot_wider() sümmeetrilised ja teevad teineteisele vastupidiseid toiminguid, st: df %>% pivot_longer(spec = spec) %>% pivot_wider(spec = spec) ja df %>% pivot_wider(spec = spec) %>% pivot_longer(spec = spec) tagastab algse df.
Kõige lihtsam näide tabeli viimisest laiasse vormingusse
Funktsiooni töö demonstreerimiseks pivot_wider() kasutame andmekogumit fish_encounters, mis sisaldab teavet selle kohta, kuidas erinevad jaamad fikseerivad kalade liikumist jõges.
#> # 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 rowsEnamikul juhtudel on see tabel informatiivsem ja mugavam kasutada, kui esitada iga jaama teave 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
#> <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
#> # … veel 9 rida ja 1 rohkem muutujat: MAWSee andmed salvestavad teavet ainult siis, kui kala on jaama poolt avastatud, st kui mõni kala pole mingisuguse jaama poolt fikseeritud, ei ole neid andmeid tabelis. See tähendab, et väljundandmed täidetakse NA-ga.
Kuid sel juhul teame, et salvestuse puudumine tähendab, et kala ei ole märgatud, seega võime kasutada argumenti values_fill funktsioonis pivot_wider() ja täita 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 algvariandist
Kujutage ette, et meil on tabel, mis sisaldab toote, riigi ja aasta kombinatsiooni. Testandmestiku määramiseks saab järgmise koodi käivitada:
df %
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 rowsMeie ülesanne on laiendada andme raami nii, et üks veerg sisaldab andmeid iga toote ja riigi kombinatsiooni kohta. Selle saavutamiseks piisab, kui edastada argumenti names_from vektor, mis sisaldab ühendatavaid 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 rowsTe võite ka rakendada spetsifikatsioone sellele funktsioonile. pivot_wider(). Kuid esitamisel pivot_wider() spetsifikatsioon teostab vastupidise teisenduse pivot_longer(): luuakse veerud, mis on määratud .nimi, kasutades väärtusi .value ja teistelt veergudelt.
Selle andmestiku jaoks võite genereerida kohandatud spetsifikatsiooni, kui soovite, et igal võimaliku riigi ja toote kombinatsioonil oleks oma veerg, mitte ainult need, mis on andmetes:
spec %
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 valuedf %>% 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.594Mitmed edasijõudnud näited uue tidyr kontseptsiooni rakendamisest
Andmete korrastamine USA sissetulekute ja üüriandmete komplekti näitel
Andmestik us_rent_income sisaldab teavet keskmise sissetuleku ja üüri kohta igas osariigis Ameerikas 2017. aastal (andmestik on saadaval paketis tidycensus).
us_rent_income
#> # A tibble: 104 x 5
#> GEOID NAME variable estimate moe
#>
#> 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
#> # … veel 94 ridaSellisel kujul on andmed salvestatud andmestikus us_rent_income nendega töötamine on äärmiselt ebamugav, seetõttu sooviksime luua andmestiku, kus on veerud: rent, rent_moe, come, income_moe. On mitmeid viise, kuidas seda spetsifikatsiooni luua, kuid peamine on see, et peame genereerima iga muutujate väärtuse kombinatsiooni ja estimate/moe, seejärel genereerime veeru nime.
spec %
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_moeSelle spetsifikatsiooni esitamine pivot_wider() annab meile tulemuse, mida otsime:
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 rowsMaailmapank
Mõnikord nõuab andmekogumi viimine soovitud vormi mitmeid samme.
Andmestik 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 andmestik, kus iga muutuja asub eraldi veerus. Hetkel pole selge, millised täpselt sammud on vajalikud, kuid alustame kõige ilmsema probleemiga: aasta on jaotatud mitmesse veergu.
Selle parandamiseks on vaja kasutada funktsiooni pivot_longer().
pop2 %
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 rowsJärgmine samm on vaadata muutujat indicator.
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 4752Kus SP.POP.GROW – rahvastiku kasv, SP.POP.TOTL – rahvastiku kogus, ning SP.URB. * on sama asi, kuid ainult linnapiirkondade kohta. Jagame need väärtused kahe muutujaga: area – piirkond (total või urban) ja muutuja, mis sisaldab tegelikke andmeid (population või growth):
pop3 %
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 rowsNüüd peame vaid jagama muutuja variable kaheks veeruks:
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 rowsKontaktide loend
Viimane näide, kujutage ette, et teil on kontaktide nimekiri, mille olete kopeerinud ja kleepinud veebisaidilt:
contacts <- tribble(
~field, ~value,
"name", "Jiena McLellan",
"company", "Toyota",
"name", "John Smith",
"company", "google",
"email", "john@google.com",
"name", "Huxley Ratcliffe"
)Selle nimekirja vormistamine tabelivormingusse on üsna keeruline, kuna puudub muutuja, mis tuvastaks, millised andmed kuuluvad konkreetsele kontaktile. Saame seda parandada, märkides, et iga uue kontakti andmed algavad nimega ("name"), seega saame luua unikaalse identifikaatori, mille väärtust suurendame üksuse võrra iga kord, kui veerus field esineb väärtus “name”:
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 john@google.com 2
#> 6 name Huxley Ratcliffe 3Nüüd, kui meil on iga kontakti jaoks ainulaadne identifikaator, saame pöörata välja välja ja väärtuse veergudesse:
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 john@google.com
#> 3 3 Huxley Ratcliffe <NA> <NA>Kokkuvõte
Isiklikult arvan, et uus kontseptsioon tidyr on tõeliselt intuitiivselt arusaadavam ja ületab oluliselt vananenud funktsioone spread() ja gather(). Loodan, et see artikkel aitas teil paremini aru saada pivot_longer() ja pivot_wider().
Allikas: habr.com
