Paketa R tidyr dhe funksionet e saj të reja pivot_longer dhe pivot_wider

Paketa tidyr bĂ«nĂ« pjesĂ« nĂ« bĂ«rthamĂ«n e njĂ« prej bibliotekave mĂ« tĂ« njohura nĂ« gjuhĂ«n R — tidyverse.
Qëllimi kryesor i paketës është të sjellë të dhënat në një formë të organizuar.

Në Habrë tashmë ekziston publikimi e dedikuar për këtë paketë, por është e datuar në vitin 2015. Unë dua të flas për ndryshimet më të rëndësishme, për të cilat autori i saj, Hadley Wickham, njoftoi para disa ditësh.

Paketa R tidyr dhe funksionet e saj të reja pivot_longer dhe pivot_wider

SJK: A do të konsiderohen funksionet gather() dhe spread() të vjetra?

Hadley Wickham: Në një farë mënyre. Ne do të ndalojmë rekomandimin e përdorimit të këtyre funksioneve dhe do të ndalojmë rregullimin e gabimeve në to, por ato do të vazhdojnë të jenë të pranishme në paketë në gjendjen aktuale.

Përmbajtja

Nëse jeni të interesuar për analizën e të dhënave, ndoshta do t'ju interesojnë kanalet e mia telegram dhe youtube Shumica e përmbajtjes së tyre është e dedikuar gjuhës R.

Koncepti TidyData

QĂ«llimi tidyr — pĂ«r t'ju ndihmuar tĂ« sjellni tĂ« dhĂ«nat nĂ« njĂ« formĂ« tĂ« organizuar. TĂ« dhĂ«nat e organizuara janĂ« ato ku:

  • Çdo variabĂ«l Ă«shtĂ« nĂ« njĂ« kolonĂ«.
  • Çdo vĂ«zhgim Ă«shtĂ« njĂ« rresht.
  • Çdo vlerĂ« Ă«shtĂ« njĂ« celul.

Me të dhënat që janë sjellë në formën tidy data, është shumë më e lehtë të punoni gjatë analizes.

Funksionet kryesore që përfshihen në paketën tidyr

tidyr përmban një grup funksionesh të dizajnuara për transformimin e tabelave:

  • fill() — mbushja e vlerave tĂ« humbura nĂ« kolonĂ« me vlerat pĂ«rpara;
  • separate() — ndan njĂ« fushĂ« nĂ« disa nĂ«pĂ«rmjet ndarĂ«sit;
  • unite() — bĂ«n operacionin e bashkimit tĂ« disa fushave nĂ« njĂ«, njĂ« veprim i kundĂ«rt me funksionin separate();
  • pivot_longer() — funksioni qĂ« transformon tĂ« dhĂ«nat nga formati i gjerĂ« nĂ« tĂ« gjatĂ«;
  • pivot_wider() — funksioni qĂ« transformon tĂ« dhĂ«nat nga formati i gjatĂ« nĂ« tĂ« gjerĂ«. Operacioni i kundĂ«rt i asaj qĂ« bĂ«n funksioni pivot_longer().
  • gather()i vjetruar — funksioni qĂ« transformon tĂ« dhĂ«nat nga formati i gjerĂ« nĂ« tĂ« gjatĂ«;
  • spread()i vjetruar — funksioni qĂ« transformon tĂ« dhĂ«nat nga formati i gjatĂ« nĂ« tĂ« gjerĂ«. Operacioni i kundĂ«rt i asaj qĂ« bĂ«n funksioni gather().

Një koncept i ri për transformimin e të dhënave nga formati i gjerë në të gjatë dhe anasjelltas

Më parë për këtë lloj transformimi ishin përdorur funksionet gather() dhe spread(). Në vitet e ekzistencës së këtyre funksioneve, është bërë e qartë se për shumicën e përdoruesve, përfshirë autorin e paketës, emrat e këtyre funksioneve dhe argumenteve të tyre ishin mjaft të paqarta, duke shkaktuar vështirësi në kërkimin dhe kuptimin se cili nga këto funksione sillte frame-in e të dhënave nga formati i gjerë në të gjatë dhe anasjelltas.

Për këtë arsye, në tidyr janë shtuar dy funksione të reja, të rëndësishme, të dizajnuara për transformimin e frame-ve të të dhënave.

Funkcionet e reja pivot_longer() dhe pivot_wider() kanë qenë të frymëzuar nga disa funksione nga paketa cdata, e krijuar nga John Mount dhe Nina Zumel.

Instaloni versionin më të fundit të tidyr 0.8.3.9000

Për të instaluar versionin e ri, më të fundit të paketës tidyr 0.8.3.9000, në të cilin funksionet e reja janë të disponueshme, përdorni kodin e mëposhtëm.

devtools::install_github("tidyverse/tidyr")

Në kohën e shkrimit të këtij artikulli, këto funksione janë të disponueshme vetëm në versionin dev të paketës në GitHub.

Kalim në funksionet e reja

Në të vërtetë, të kalosh skriptet e vjetra për të punuar me funksionet e reja nuk është e vështirë; për më shumë kuptim, do të marr një shembull nga dokumentacioni i funksioneve të vjetra dhe do të tregoj si këto operacione kryhen me ndihmën e titujve të rinj pivot_*() funksione.

Transformimi i formatit të gjerë në të gjatë.

Shembulli i kodit nga dokumentacioni i funksionit gather

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

Transformimi i formatit të gjatë në të gjerë.

Shembulli i kodit nga dokumentacioni i funksionit spread

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

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

Duke qenë se në shembujt e mësipërm të punës me pivot_longer() dhe pivot_wider(), në tabelën e origjinës stocks nuk ka kolonash të përmendura në argumentet names_to dhe values_to emrat e tyre duhet të përcaktohen në thonjëza.

Tabela me të cilën do t'ju jetë më e lehtë të kuptoni se si të kaloni në punën me konceptin e ri tidyr.

Paketa R tidyr dhe funksionet e saj të reja pivot_longer dhe pivot_wider

Vërejtje nga autori

I gjithë teksti i mëpasshëm është një përkthim adaptiv, madje mund ta quaja përkthim të lirë vignettes nga faqja zyrtare e bibliotekës tidyverse.

Një shembull i thjeshtë i transformimit të të dhënave nga formati i gjerë në të gjatë

pivot_longer () — bĂ«n setet e tĂ« dhĂ«nave mĂ« tĂ« gjatĂ«, duke reduktuar numrin e kolonnave dhe duke rritur numrin e rreshtave.

Paketa R tidyr dhe funksionet e saj të reja pivot_longer dhe pivot_wider

Për të realizuar shembujt e paraqitur në artikull, fillimisht është e nevojshme të ngarkoni paketat e nevojshme:

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

Le të supozojmë se kemi një tabelë me rezultatet e një ankete, në të cilën (ndër të tjera) iu kërkua njerëzve për besimin e tyre dhe të ardhurat e tyre vjetore:

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

Ky tabela përmban të dhëna mbi fenë e respondentëve në rreshta, ndërsa nivelet e të ardhurave janë shpërndarë në emrat e kolonave. Numri i respondentëve nga çdo kategori ruhet në vlerat e qelizave në ndërthyerjen e fesë dhe nivelit të të ardhurave. Për ta sjellë tabelën në një format të pastër dhe të saktë, mjafton të përdorni pivot_longer():

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

pew %>% 
  pivot_longer(cols = -religion, names_to = "income", values_to = "count")
#> # Një tibble: 180 x 3
#>    religion income             count
#>                      
#>  1 Agnostik   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 Nuk e di/refuzuar    96
#> # 
 me 170 rreshta të tjera

Argumentet e funksionit pivot_longer()

  • Argumenti i parĂ« cols, pĂ«rshkruan, cilat kolona duhet tĂ« bashkohen. NĂ« kĂ«tĂ« rast, tĂ« gjitha kolonat, pĂ«rveç time.
  • Argumenti names_to i jep emrin e variablit qĂ« do tĂ« krijohet nga emrat e kolonave qĂ« kemi bashkuar.
  • values_to i jep emrin e variablit qĂ« do tĂ« krijohet nga tĂ« dhĂ«nat qĂ« ruhen nĂ« vlerat e qelizave tĂ« kolonave tĂ« bashkuara.

Specifikimet

Ky është një funksionalitet i ri i paketës tidyr, i cili më parë, duke punuar me funksione të vjetruara, nuk ishte në dispozicion.

Specifikimi është një kadër të dhënash, çdo rresht i të cilit i përkon një kolone në kadrin e të dhënave të reja, si dhe dy kolona speciale që fillojnë me:

  • .emĂ«r pĂ«rmban emrin origjinal tĂ« kolonĂ«s.
  • .value pĂ«rmban emrin e kolonĂ«s, nĂ« tĂ« cilĂ«n do tĂ« futen vlerat e qelizave.

Kolonat e tjera të specifikimit pasqyrojnë se si do të shfaqet emri i kolonave të kompresuara në .emër.

Specifikimi përshkruan metadata që ruhen në emrin e kolonës, me një rresht për çdo kolonë dhe një kolone për çdo variabël të bashkuar me emrin e kolonës, ndoshta tani ky përkufizim duket i ndërlikuar, por pas shqyrtimit të disa shembujve gjithçka do të bëhet shumë më e qartë.

Kërkesa e specifikimit është që ju mund të nxirrni, modifikoni dhe vendosni metadata të reja për kadrin e të dhënave të transformuar.

Për të punuar me specifikacione kur transformoni tabelën nga formati i gjerë në të gjatë, shërben funksioni pivot_longer_spec().

Si funksionon ky funksion, ai merr çdo kadrin e të dhënave dhe formon metadatën e tij në mënyrën e përshkruar më sipër.

Për shembull, le të marrim grupin e të dhënave që ofrohet me paketën tidyr. Ky grup të dhënash përmban informacion të ofruar nga Organizata Botërore e Shëndetësisë mbi sëmundshmërinë e tuberkulozit.

who
#> # Një tibble: 7,240 x 60
#>    country iso2  iso3   year new_sp_m014 new_sp_m1524 new_sp_m2534
#>        <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
#> # 
 me 7,230 rreshta të tjera, dhe 53 variabla të tjerë

Le ta nisim specifikimin e tij.

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 rows

Fushat country, iso2, iso3 tani që janë variabla. Detyra jonë është të përmbysim kolonat me new_sp_m014 për newrel_f65.

Në emrat e këtyre kolonave ruhet informacioni në vijim:

  • Prefiksi new_ tregon se pĂ«rmban tĂ« dhĂ«na mbi rastet e reja tĂ« sĂ«mundjes sĂ« tuberkulozit, modeli i tanishĂ«m i tĂ« dhĂ«nave pĂ«rmban informacion vetĂ«m pĂ«r rastet e reja, prandaj ky prefiks nuk ka asnjĂ« pĂ«rcaktim nĂ« kĂ«tĂ« kontekst.
  • sp/rel/sp/ep pĂ«rshkruan metodĂ«n e diagnozĂ«s sĂ« sĂ«mundjes.
  • m/f gjinia e pacientit.
  • 014/1524/2535/3544/4554/65 grupi moshor i pacientit.

Ne mund të ndajmë këto kolona duke përdorur funksionin extract(), duke përdorur shprehjen e rregullt.

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

Vini re, kolona .emër duhet të mbetet e pandryshuar, pasi është indeksi ynë në emrat e kolonave të grupit të të dhënave origjinale.

Gjinia dhe mosha (kolonat gender dhe age) kanë vlera fikse dhe të njohura, prandaj është e rekomandueshme t'i transformojmë këto kolona në faktorë:

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

Në fund, për të aplikuar specifikimin që krijuam në kadrin tonë të të dhënave who na nevojitet të përdorim argumentin spec në funksionin 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

Gjithçka që sapo bëmë mund të ilustrohet në këtë mënyrë:

Paketa R tidyr dhe funksionet e saj të reja pivot_longer dhe pivot_wider

Specifikimi duke përdorur disa vlera (.value)

Në shembullin e mësipërm, kolona e specifikimit .value përmbante vetëm një vlerë, në shumicën e rasteve kështu ndodh.

Por ndodhin herë pas here situata kur është e nevojshme të mblidhen të dhëna nga kolona me tipe të ndryshme të të dhënave. Me funksionin e vjetruar, spread() do të ishte mjaft e vështirë ta bënit këtë.

Shembulli i mëposhtëm është marrë nga vignettes në paketën data.table.

Le të krijojmë një dataframe për trajnimin.

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             1

Dataframe i krijuar në çdo rresht përmban të dhënat për fëmijët e një familjeje. Në familje mund të ketë një ose dy fëmijë. Për secilin fëmijë ofrohen të dhëna për datën e lindjes dhe gjininë, ku të dhënat për secilin fëmijë janë në kolona të ndara; detyra jonë është t'i sjellim këto të dhëna në formatin e duhur për analizë.

Vini re se kemi dy variabla me informacion për çdo fëmijë: gjinia dhe data e lindjes (kolonat me prefiksin dop përmbajnë datën e lindjes, ndërsa kolonat me prefiksin gender përmbajnë gjininë e fëmijës). Në rezultatin e pritur ato duhet të jenë në kolona të ndara. Ne mund ta bëjmë këtë duke gjeneruar një specifikim, ku kolona .value do të ketë dy vlera të ndryshme.

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     2

Tani le të shqyrtojmë hap pas hapi veprimet që kryhen nga kodi i mësipërm.

  • pivot_longer_spec(-family) — krijon njĂ« specifikim qĂ« ngushton tĂ« gjitha kolonat e disponueshme, pĂ«rveç kolonĂ«s family.
  • separate(col = name, into = c(".value", "child")) — ndan kolonĂ«n .emĂ«r, e cila pĂ«rmban emrat e fushave origjinale, sipas nĂ«nvizĂ«s dhe regjistron vlerat e marra nĂ« kolona. .value dhe child.
  • mutate(child = parse_number(child)) — konverton vlerat e fushĂ«s child nga tipin tekstual nĂ« tipin numerik.

Tani ne mund të aplikojmë specifikimin e marrë në dataframe origjinal dhe ta sjellim tabelën në formatin e dëshiruar.

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

Ne përdorim argumentin na.rm = TRUE, sepse forma aktuale e të dhënave e detyron të krijojmë rreshta të panevojshëm për vëzhgimet që nuk ekzistojnë. Meqenëse familja 2 ka vetëm një fëmijë, na.rm = TRUE siguron që familja 2 do të ketë një rresht në të dhënat e daljes.

Transformimi i frame-ve të të dhënave nga formati i gjatë në të gjerë

pivot_wider() — Ă«shtĂ« njĂ« transformim nĂ« tĂ« kundĂ«rt, dhe pĂ«rkundrazi rrit numrin e kolonave tĂ« dataframe-it duke zvogĂ«luar numrin e rreshtave.

Paketa R tidyr dhe funksionet e saj të reja pivot_longer dhe pivot_wider

Ky lloj transformimi është jashtëzakonisht i rrallë për të sjellë të dhënat në një pamje të pastër, megjithatë ky teknik mund të jetë i dobishëm për të krijuar tabela përmbledhëse që përdoren në prezantime, ose për integrimin me mjete të tjera.

Në të vërtetë, funksionet pivot_longer() dhe pivot_wider() janë simetrike dhe ushtrojnë veprime të kundërta ndaj njëri-tjetrit, pra: df %>% pivot_longer(spec = spec) %>% pivot_wider(spec = spec) dhe df %>% pivot_wider(spec = spec) %>% pivot_longer(spec = spec) do të kthejë df-në origjinale.

Shembulli më i thjeshtë i sjelljes së një tabele në format të gjerë

Për të demonstruar funksionimin e funksionit pivot_wider() ne do të përdorim të dhënat fish_encounters, e cila ruan informacion mbi atë se si stacionet e ndryshme regjistrojnë lëvizjen e peshqve në lum.

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

Në shumicën e rasteve, kjo tabelë do të jetë më informative dhe e lehtë për t'u përdorur nëse paraqesim informacionin për çdo stacion në një kolonë të veçantë.

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
#>        &   &    & & & & &
#>  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
#> # 
 me 9 rreshta më shumë dhe 1 variabël më shumë: MAW

Ky set të dhënash regjistron informacion vetëm kur peshku është konstatuar nga stacioni, pra nëse ndonjë peshk nuk është regjistruar nga ndonjë stacion, atëherë këto të dhëna nuk do të jenë në tabelë. Kjo do të thotë se të dhënat e daljes do të mbushen me NA.

Megjithatë, në këtë rast ne e dimë se mungesa e regjistrimit do të thotë që peshku nuk është bërë i dukshëm, kështu që mund të përdorim argumentin values_fill në funksionin pivot_wider() dhe të mbushim këto vlera të humbura me zero:

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>

Gjenerimi i emrit të kolonës nga disa variabla burimorë

Imagjinoni që kemi një tabelë që përmban kombinime produkti, shteti dhe viti. Për të gjeneruar një data frame testues, mund të ekzekutoni këtë kod:

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 rows

Detyra jonë është të zgjeronim data frame-in ndërsa një kolonë të përmbante të dhënat për çdo kombinim produkti dhe shteti. Për këtë, mjafton të kaloni në argumentin names_from një vektor që përmban emrat e fushave që do të bashkohen.

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

Gjashtas mund të aplikoni specifikime në funksionin pivot_wider(). Por në parashqitjen e pivot_wider() specifikimi bën një transformim të kundërt pivot_longer(): krijohen kolonat e përmendur në .emër, duke përdorur vlerat nga .value dhe kolonat e tjera.

Për këtë set të dhënash, mund të gjeneroni një specifikim të personalizuar nëse dëshironi që çdo kombinim të mundshëm të shtetit dhe produktit të ketë kolonë të vetën, jo vetëm ato që janë të pranishme në të dhëna:

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

Disa shembuj më të avancuar të punës me konceptin e ri tidyr

Shtyrja e të dhënave në një formë të organizuar me shembuj nga kompleti i të dhënave për popullsinë dhe qiradhënien në SHBA

Seti i të dhënave us_rent_income përmban informacione mbi mesataren e të ardhurave dhe qirave për çdo shtet në SHBA për vitin 2017 (seti i të dhënave është në paketën 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
#> # 
 me 94 rreshta të tjerë

Në formën e saj, siç ruhen të dhënat në datasetin us_rent_income punimi me to është ekstremisht i vështirë, prandaj do të doja të krijoja një set të dhënash me kolonat: rent, rent_moe, come, income_moe. Ekzistojnë shumë mënyra për të krijuar këtë specifikim, por e rëndësishme është që duhet të gjenerojmë çdo kombinim të vlerave të variables dhe estimate/moe, dhe më pas të krijojmë emrin e kolonës.

  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_moe

Ofrimi i këtij specifikimi pivot_wider() na jep rezultatin që kërkojmë:

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

Bankën Botërore

Ndonjëherë, të sjellësh setin e të dhënave në formën e duhur kërkon disa hapa.
Dataseti world_bank_pop përmban të dhëna nga banka botërore mbi popullsinë e çdo vendi në periudhën 2000 deri në 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>

Qëllimi ynë është të krijojmë një set të dhënash të rregullt ku çdo variable ndodhet në një kolonë të veçantë. Deri tani, është e paqartë se cilat hapa janë të nevojshëm, por do të fillojmë me problemin më të dukshëm: viti është shpërndarë në disa kolona.

Për ta korrigjuar atë, është e nevojshme të përdoret funksioni 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 rows

Hapi tjetër është të shqyrtojmë variable-n 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  4752

Ku SP.POP.GROW Ă«shtĂ« rritja e popullsisĂ«, SP.POP.TOTL Ă«shtĂ« numri total i popullsisĂ«, dhe SP.URB. * Ă«shtĂ« e njĂ«jta gjĂ«, por vetĂ«m pĂ«r zonat urbane. Le tĂ« ndarim kĂ«to vlera nĂ« dy variable: area — vendi (total ose urban) dhe njĂ« variable qĂ« pĂ«rmban tĂ« dhĂ«nat efektive (population ose 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 rows

Tani na mbetet vetëm të ndajmë variable-n variable në dy kolona:

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

Lista e kontakteve

Shembulli i fundit, imagjinoni që keni një listë kontaktesh që e keni kopjuar dhe ngjitur nga një web faqe:

contacts <- tribble(
  ~field, ~value,
  "name", "Jiena McLellan",
  "company", "Toyota", 
  "name", "John Smith", 
  "company", "google", 
  "email", "john@google.com",
  "name", "Huxley Ratcliffe"
)

Të sjellësh këtë listë në formë tabulare është mjaft e vështirë, sepse nuk ka një variable që identifikon se cilat të dhëna i përkasin cilit kontakt. Mund ta korrigjojmë këtë duke vënë re se të dhënat për çdo kontakt të ri fillojnë me emrin ("name"), prandaj mund të krijojmë një identifikues unik, duke e rritur me një çdo herë që vlera "name" shfaqet në kolonën field:

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         3

Tani, kur kemi një identifikues unik për çdo kontakt, mund të kthejmë fushën dhe vlerën në kolona:

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>

Përfundimi

Mendimi im personal është se koncepti i ri tidyr është vërtet intuitivisht më i qartë, dhe ndjeshëm superior në funksionalitet ndaj funksioneve të të kaluara spread() dhe gather(). Shpresoj që ky artikull ju ka ndihmuar të kuptoni pivot_longer() dhe pivot_wider().

Burimi: habr.com

Bli njĂ« hosting tĂ« besueshĂ«m pĂ«r faqet me mbrojtje DDoS, VPS VDS serverĂ« đŸ”„ Bli njĂ« hosting tĂ« besueshĂ«m pĂ«r faqet me mbrojtje DDoS, VPS VDS serverĂ« | ProHoster