ProHoster > Blog > yönetim > R paketi tidyr ve yeni fonksiyonları pivot_longer ve pivot_wider
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.
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.
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ı.
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.
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:
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():
İ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")
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.
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:
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.
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.
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.
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)
#> # 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:
Ü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.
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:
#> # 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.
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.
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().
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):
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:
#> # 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:
#> # 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().