R paketi tidyr ve yeni fonksiyonları pivot_longer ve pivot_wider

Paket toparlayıcı R dilindeki en popüler kütüphanelerden birinin çekirdeğine dahil edilmiştir - tidyverse.
Paketin temel amacı verileri doğru bir forma dönüştürmektir.

Habré'de zaten mevcut yayın bu pakete adanmıştır, ancak 2015 yılına kadar uzanır. Ve size birkaç gün önce yazarı Hedley Wickham tarafından duyurulan en güncel değişikliklerden bahsetmek istiyorum.

R paketi tidyr ve yeni fonksiyonları pivot_longer ve pivot_wider

SJK: Collect() ve spread() kullanımdan kaldırılacak mı?

Hadley Wickham: Bir dereceye kadar. Artık bu işlevlerin kullanılmasını önermeyeceğiz ve bunlardaki hataları düzeltmeyeceğiz, ancak mevcut durumlarıyla pakette bulunmaya devam edecekler.

Içerik

Veri analiziyle ilgileniyorsanız, benim ilginizi çekebilir telgraf и Youtube kanallar. İçeriğin çoğu R diline ayrılmıştır.

TidyData konsepti

Gol toparlayıcı — verileri düzgün bir forma dönüştürmenize yardımcı olur. Düzgün veri, aşağıdaki durumlardaki verilerdir:

  • Her değişken bir sütundadır.
  • Her gözlem bir dizedir.
  • Her değer bir hücredir.

Analiz yaparken düzenli verilerle sunulan verilerle çalışmak çok daha kolay ve kullanışlıdır.

Tidyr paketinde yer alan ana işlevler

tidyr, tabloları dönüştürmek için tasarlanmış bir dizi işlev içerir:

  • fill() - bir sütundaki eksik değerlerin önceki değerlerle doldurulması;
  • separate() — bir ayırıcıyı kullanarak bir alanı birkaç alana böler;
  • unite() - birkaç alanı tek bir alanda birleştirme işlemini gerçekleştirir, işlevin ters eylemi separate();
  • pivot_longer() — verileri geniş formattan uzun formata dönüştüren bir işlev;
  • pivot_wider() - verileri uzun formattan geniş formata dönüştüren bir işlev. Fonksiyon tarafından gerçekleştirilen işlemin tersi işlem pivot_longer().
  • gather()eski — verileri geniş formattan uzun formata dönüştüren bir işlev;
  • spread()eski - verileri uzun formattan geniş formata dönüştüren bir işlev. Fonksiyon tarafından gerçekleştirilen işlemin tersi işlem gather().

Verileri geniş formattan uzun formata ve tersi yönde dönüştürmek için yeni konsept

Daha önce bu tür dönüşümler için işlevler kullanılıyordu gather() и spread(). Bu işlevlerin var olduğu yıllar boyunca, paketin yazarı da dahil olmak üzere çoğu kullanıcı için bu işlevlerin adlarının ve argümanlarının pek açık olmadığı ve bunları bulmada ve bu işlevlerden hangisinin dönüştürüldüğünü anlamada zorluklara neden olduğu ortaya çıktı. geniş formattan uzun formata ve tam tersi bir tarih çerçevesi.

Bu bağlamda, toparlayıcı Tarih çerçevelerini dönüştürmek için tasarlanmış iki yeni önemli işlev eklendi.

Yeni Özellikler pivot_longer() и pivot_wider() paketteki bazı özelliklerden ilham aldı cdataJohn Mount ve Nina Zumel tarafından yaratılmıştır.

Tidyr 0.8.3.9000'in en güncel versiyonunun kurulması

Paketin yeni ve en güncel sürümünü yüklemek için toparlayıcı 0.8.3.9000Yeni özelliklerin mevcut olduğu yerlerde aşağıdaki kodu kullanın.

devtools::install_github("tidyverse/tidyr")

Bu yazının yazıldığı sırada bu işlevler yalnızca paketin GitHub'daki geliştirme sürümünde mevcuttur.

Yeni özelliklere geçiş

Aslında eski scriptleri yeni fonksiyonlarla çalışacak şekilde aktarmak zor değil; daha iyi anlaşılması için eski fonksiyonların dokümantasyonundan bir örnek alıp aynı işlemlerin yenilerini kullanarak nasıl yapıldığını göstereceğim. pivot_*() fonksiyonlar.

Geniş formatı uzun formata dönüştürün.

Toplama işlevi belgelerinden örnek kod

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

Uzun formatı geniş formata dönüştürme.

Yayılma işlevi belgelerinden örnek kod

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

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

Çünkü yukarıdaki çalışma örneklerinde pivot_longer() и pivot_wider(), orijinal tabloda hisse senetleri bağımsız değişkenlerde sütun listelenmiyor name_to и değerler_to adları tırnak içinde olmalıdır.

Yeni bir konseptle çalışmaya nasıl geçeceğinizi en kolay şekilde anlamanıza yardımcı olacak bir tablo toparlayıcı.

R paketi tidyr ve yeni fonksiyonları pivot_longer ve pivot_wider

Yazardan not

Aşağıdaki metnin tamamı uyarlanabilir, hatta ücretsiz çeviri diyebilirim vinyetler resmi tidyverse kütüphane web sitesinden.

Verileri geniş formattan uzun formata dönüştürmenin basit bir örneği

pivot_longer () — Sütun sayısını azaltarak ve satır sayısını artırarak veri kümelerini daha uzun hale getirir.

R paketi tidyr ve yeni fonksiyonları pivot_longer ve pivot_wider

Makalede sunulan örnekleri çalıştırmak için öncelikle gerekli paketleri bağlamanız gerekir:

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

Diyelim ki (diğer şeylerin yanı sıra) insanlara dinlerini ve yıllık gelirlerini soran bir anketin sonuçlarını içeren bir tablomuz var:

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

Bu tablo, yanıt verenlerin din verilerini satırlar halinde içerir ve gelir düzeyleri sütun adlarına dağılmıştır. Her kategoriden yanıt verenlerin sayısı, din ve gelir düzeyinin kesiştiği hücre değerlerinde saklanmaktadır. Tabloyu düzgün ve doğru bir formata getirmek için şunu kullanmak yeterlidir: 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

Fonksiyon Argümanları pivot_longer()

  • İlk argüman yaka, hangi sütunların birleştirilmesi gerektiğini açıklar. Bu durumda, hariç tüm sütunlar zaman.
  • tartışma name_to birleştirdiğimiz sütunların adlarından oluşturulacak değişkenin adını verir.
  • değerler_to birleştirilen sütunların hücrelerindeki değerlerde saklanan verilerden oluşturulacak değişkenin adını verir.

şartname

Bu paketin yeni bir işlevidir toparlayıcıEski işlevlerle çalışırken daha önce kullanılamayan bir özellik.

Belirtim, her satırı yeni çıktı tarih çerçevesindeki bir sütuna ve şununla başlayan iki özel sütuna karşılık gelen bir veri çerçevesidir:

  • . İsim orijinal sütun adını içerir.
  • .değer hücre değerlerini içerecek sütunun adını içerir.

Belirtimin geri kalan sütunları, yeni sütunun sıkıştırılmış sütunların adını nasıl görüntüleyeceğini yansıtır. . İsim.

Spesifikasyon, bir sütun adında saklanan meta verileri, her sütun için bir satır ve her değişken için bir sütunla birlikte sütun adıyla birlikte açıklar; bu tanım şu anda kafa karıştırıcı görünebilir, ancak birkaç örneğe baktıktan sonra daha da anlaşılacaktır. daha net.

Spesifikasyonun amacı, dönüştürülmekte olan veri çerçevesi için yeni meta verileri alabilmeniz, değiştirebilmeniz ve tanımlayabilmenizdir.

Bir tabloyu geniş formattan uzun formata dönüştürürken spesifikasyonlarla çalışmak için işlevi kullanın. pivot_longer_spec().

Bu işlevin çalışma şekli, herhangi bir tarih çerçevesini alması ve meta verilerini yukarıda açıklanan şekilde üretmesidir.

Örnek olarak paketle birlikte verilen who veri kümesini ele alalım. toparlayıcı. Bu veri seti, uluslararası sağlık örgütünün tüberküloz görülme sıklığına ilişkin sağladığı bilgileri içermektedir.

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

Onun spesifikasyonunu oluşturalım.

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

Tarla ülke, iso2, iso3 zaten değişkenler. Görevimiz sütunları çevirmektir. new_sp_m014 üzerinde newrel_f65.

Bu sütunların adları aşağıdaki bilgileri saklar:

  • Önek new_ sütunun yeni tüberküloz vakalarına ilişkin veriler içerdiğini, mevcut tarih çerçevesinin yalnızca yeni hastalıklara ilişkin bilgiler içerdiğini, dolayısıyla bu önekin mevcut bağlamda herhangi bir anlam taşımadığını belirtir.
  • sp/rel/sp/ep Bir hastalığın teşhisine yönelik bir yöntemi açıklar.
  • m/f hastanın cinsiyeti.
  • 014/1524/2535/3544/4554/65 hasta yaş aralığı.

Bu sütunları işlevi kullanarak bölebiliriz. extract()düzenli ifade kullanarak.

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

Lütfen sütuna dikkat edin . İsim Bu, orijinal veri kümesinin sütun adlarındaki dizinimiz olduğundan değişmeden kalmalıdır.

Cinsiyet ve yaş (sütunlar cinsiyet и yaş) sabit ve bilinen değerlere sahip olduğundan, bu sütunların faktörlere dönüştürülmesi önerilir:

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

Son olarak oluşturduğumuz spesifikasyonu orijinal tarih çerçevesine uygulayabilmek için kim bir argüman kullanmamız gerekiyor spec işlevde 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

Az önce yaptığımız her şey şematik olarak aşağıdaki gibi tasvir edilebilir:

R paketi tidyr ve yeni fonksiyonları pivot_longer ve pivot_wider

Birden fazla değer kullanan spesifikasyon (.value)

Yukarıdaki örnekte spesifikasyon sütunu .değer yalnızca bir değer içeriyordu; çoğu durumda durum böyledir.

Ancak bazen değerlerde farklı veri türlerine sahip sütunlardan veri toplamanız gerektiğinde bir durum ortaya çıkabilir. Eski bir işlevi kullanma spread() bunu yapmak oldukça zor olacaktır.

Aşağıdaki örnek şuradan alınmıştır: vinyetler pakete veri tablosu.

Bir eğitim veri çerçevesi oluşturalım.

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

Oluşturulan tarih çerçevesi, her satırda bir ailenin çocuklarına ilişkin verileri içermektedir. Ailelerin bir veya iki çocuğu olabilir. Her çocuk için doğum tarihi ve cinsiyete ilişkin veriler sağlanmakta ve her çocuğa ait veriler ayrı sütunlarda yer almaktadır; bizim görevimiz bu verileri analiz için doğru formata getirmektir.

Lütfen her çocuk hakkında bilgi içeren iki değişkenimiz olduğunu unutmayın: cinsiyeti ve doğum tarihi (önek içeren sütunlar) tıpa doğum tarihini ve öneki olan sütunları içerir cinsiyet çocuğun cinsiyetini içerir). Beklenen sonuç, bunların ayrı sütunlarda görünmesi gerektiğidir. Bunu, sütunun bulunduğu bir spesifikasyon oluşturarak yapabiliriz. .value iki farklı anlamı olacaktır.

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

Şimdi yukarıdaki kodun gerçekleştirdiği işlemlere adım adım bakalım.

  • pivot_longer_spec(-family) — aile sütunu dışındaki tüm mevcut sütunları sıkıştıran bir spesifikasyon oluşturun.
  • separate(col = name, into = c(".value", "child")) - sütunu böl . İsimkaynak alanların adlarını içeren, alt çizgiyi kullanan ve elde edilen değerleri sütunlara giren .değer и çocuk.
  • mutate(child = parse_number(child)) — alan değerlerini dönüştürün çocuk metinden sayısal veri türüne.

Artık ortaya çıkan spesifikasyonu orijinal veri çerçevesine uygulayabilir ve tabloyu istenilen forma getirebiliriz.

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

Argüman kullanıyoruz na.rm = TRUEçünkü verinin mevcut biçimi, var olmayan gözlemler için fazladan satırların oluşturulmasını zorunlu kılmaktadır. Çünkü 2. ailenin tek çocuğu var, na.rm = TRUE aile 2'nin çıktıda bir satıra sahip olacağını garanti eder.

Tarih çerçevelerini uzun formattan geniş formata dönüştürme

pivot_wider() - ters dönüşümdür ve bunun tersi de satır sayısını azaltarak tarih çerçevesinin sütun sayısını artırır.

R paketi tidyr ve yeni fonksiyonları pivot_longer ve pivot_wider

Bu tür bir dönüşüm, verileri doğru bir forma getirmek için son derece nadiren kullanılır, ancak bu teknik, sunumlarda kullanılan pivot tabloların oluşturulmasında veya diğer bazı araçlarla entegrasyon için yararlı olabilir.

Aslında işlevler pivot_longer() и pivot_wider() simetriktir ve birbirine ters eylemler üretir, yani: df %>% pivot_longer(spec = spec) %>% pivot_wider(spec = spec) и df %>% pivot_wider(spec = spec) %>% pivot_longer(spec = spec) orijinal df'yi döndürecektir.

Bir tabloyu geniş formata dönüştürmenin en basit örneği

Fonksiyonun nasıl çalıştığını göstermek için pivot_wider() veri kümesini kullanacağız balık_karşılaşmalarıfarklı istasyonların balıkların nehir boyunca hareketini nasıl kaydettiği hakkında bilgi depolayan.

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

Çoğu durumda, her istasyona ilişkin bilgileri ayrı bir sütunda sunarsanız bu tablo daha bilgilendirici ve kullanımı daha kolay olacaktır.

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>

Bu veri seti yalnızca istasyon tarafından balık tespit edildiğinde bilgileri kaydeder; herhangi bir istasyon tarafından herhangi bir balık kaydedilmemişse, bu veriler tabloda olmayacaktır. Bu, çıktının NA ile doldurulacağı anlamına gelir.

Ancak bu durumda kayıt olmamasının balığın görülmediği anlamına geldiğini bildiğimiz için bu argümanı kullanabiliriz. değerler_doldurma işlevde pivot_wider() ve bu eksik değerleri sıfırlarla doldurun:

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>

Birden çok kaynak değişkenden sütun adı oluşturma

Ürün, ülke ve yılın birleşimini içeren bir tablomuz olduğunu düşünün. Bir test tarihi çerçevesi oluşturmak için aşağıdaki kodu çalıştırabilirsiniz:

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

Görevimiz, veri çerçevesini, bir sütunun her ürün ve ülke kombinasyonuna ilişkin verileri içerecek şekilde genişletmektir. Bunu yapmak için argümanı aktarmanız yeterli isimler_from birleştirilecek alanların adlarını içeren bir vektör.

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

Ayrıca bir işleve spesifikasyonlar uygulayabilirsiniz. pivot_wider(). Ama teslim edildiğinde pivot_wider() spesifikasyon ters dönüşümü yapar pivot_longer(): Belirtilen sütunlar . İsimdeğerleri kullanılarak .değer ve diğer sütunlar.

Bu veri kümesi için, yalnızca verilerde mevcut olanların değil, olası her ülke ve ürün kombinasyonunun kendi sütununa sahip olmasını istiyorsanız özel bir spesifikasyon oluşturabilirsiniz:

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

Yeni tidyr konseptiyle çalışmanın birkaç gelişmiş örneği

Örnek olarak ABD Nüfus Sayımı Geliri ve Kira veri kümesini kullanarak verileri temizleme.

Veri seti us_rent_income 2017 yılı için ABD'deki her eyalet için ortalama gelir ve kira bilgilerini içerir (veri seti pakette mevcuttur) düzenli nüfus sayımı).

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

Verilerin veri kümesinde saklandığı formda us_rent_income onlarla çalışmak son derece elverişsiz olduğundan sütunlu bir veri seti oluşturmak istiyoruz: kiralamak, kira_moe, nasıl, gelir_moe. Bu spesifikasyonu oluşturmanın birçok yolu vardır, ancak asıl nokta, değişken değerlerin her kombinasyonunu üretmemiz gerektiğidir ve tahmin/moeve ardından sütun adını oluşturun.

  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

Bu spesifikasyonun sağlanması pivot_wider() bize aradığımız sonucu verir:

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

Dünya Bankası

Bazen bir veri setini istenen forma getirmek birkaç adım gerektirir.
Veri kümesi world_bank_pop Her ülkenin 2000 ile 2018 yılları arasındaki nüfusuna ilişkin Dünya Bankası verilerini içerir.

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

Amacımız her değişkenin kendi sütununda yer aldığı düzgün bir veri seti oluşturmaktır. Tam olarak hangi adımların gerekli olduğu belli değil, ancak en bariz sorunla başlayacağız: yıl birden fazla sütuna yayılmış durumda.

Bunu düzeltmek için işlevi kullanmanız gerekir. 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

Bir sonraki adım gösterge değişkenine bakmaktır.
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

SP.POP.GROW nüfus artışını, SP.POP.TOTL toplam nüfusu ve SP.URB'yi ifade eder. * Aynı şey, ancak yalnızca kentsel alanlar için. Bu değerleri iki değişkene ayıralım: alan - alan (toplam veya kentsel) ve gerçek verileri içeren bir değişken (nüfus veya büyüme):

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

Şimdi tek yapmamız gereken değişkeni iki sütuna bölmek:

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

Kişi listesi

Son bir örnek olarak, bir web sitesinden kopyalayıp yapıştırdığınız bir kişi listeniz olduğunu hayal edin:

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

Bu listeyi tablolamak oldukça zordur çünkü hangi verinin hangi kişiye ait olduğunu belirleyen bir değişken yoktur. Her yeni kişinin verilerinin "ad" ile başladığını dikkate alarak bu sorunu çözebiliriz, böylece benzersiz bir tanımlayıcı oluşturabilir ve alan sütunu "ad" değerini her içerdiğinde bunu bir artırabiliriz:

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

Artık her kişi için benzersiz bir kimliğe sahip olduğumuza göre alanı ve değeri sütunlara dönüştürebiliriz:

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>

Sonuç

Kişisel görüşüm yeni konseptin toparlayıcı gerçekten daha sezgisel ve işlevsellik açısından eski işlevlere göre önemli ölçüde üstün spread() и gather(). Umarım bu makale başa çıkmanıza yardımcı olmuştur pivot_longer() и pivot_wider().

Kaynak: habr.com

Yorum ekle