包 蒂德爾 包含在 R 語言中最受歡迎的庫之一的核心中 - 整潔的.
該包的主要目的是將數據轉化為準確的形式。
已在 Habré 上提供
SJK:gather() 和 spread() 會被棄用嗎?
哈德利·威克姆(Hadley Wickham): 某種程度上。我們將不再建議使用這些函數並修復其中的錯誤,但它們將繼續以當前狀態存在於套件中。
Содержание
如果您對數據分析感興趣,您可能會對我的文章感興趣
整潔資料概念 tidyr 包中包含的主要功能 將資料從寬格式轉換為長格式,反之亦然的新概念 安裝最新版本的 tidyr 0.8.3.9000 過渡到新功能 將資料從寬格式轉換為長格式的簡單範例 產品規格 使用多個值的規範(.value) 將日期幀從長格式轉換為寬格式 使用新 tidyr 概念的幾個高級範例 結論
整潔資料概念
目標 蒂德爾 — 幫助您將資料呈現為所謂的整齊形式。整潔數據是指以下數據:
- 每個變數都在一列中。
- 每個觀察結果都是一個字串。
- 每個值都是一個儲存格。
在進行分析時,使用以整齊資料呈現的資料會更加容易和方便。
tidyr 包中包含的主要功能
tidyr 包含一組旨在轉換表的函數:
fill()
— 用先前的值填入列中的缺失值;separate()
— 使用分隔符號將一個欄位拆分為多個欄位;unite()
— 執行將多個欄位合併為一個的操作,該函數的逆操作separate()
;pivot_longer()
— 將資料從寬格式轉換為長格式的函數;pivot_wider()
- 將資料從長格式轉換為寬格式的函數。函數執行的操作的逆操作pivot_longer()
.gather()
過時的 — 將資料從寬格式轉換為長格式的函數;spread()
過時的 - 將資料從長格式轉換為寬格式的函數。函數執行的操作的逆操作gather()
.
將資料從寬格式轉換為長格式,反之亦然的新概念
以前,函數用於這種轉換 gather()
и spread()
。這些函數存在多年後,很明顯,對於大多數用戶(包括包的作者)來說,這些函數的名稱及其參數並不十分明顯,並且導致查找它們和理解這些函數中哪些函數進行轉換時遇到困難日期框從寬格式到長格式,反之亦然。
對此,在 蒂德爾 新增了兩個新的重要函數,旨在轉換日期框架。
新功能 pivot_longer()
и pivot_wider()
受到軟體包中的一些功能的啟發 數據中心,由約翰·蒙特和尼娜·祖梅爾創作。
安裝最新版本的 tidyr 0.8.3.9000
安裝最新版本的軟體包 蒂德爾 0.8.3.9000,如果有新功能可用,請使用以下程式碼。
devtools::install_github("tidyverse/tidyr")
在撰寫本文時,這些函數僅在 GitHub 上的開發版本中可用。
過渡到新功能
事實上,遷移舊腳本來使用新函數並不困難;為了更好地理解,我將從舊函數的文件中舉出一個例子,展示如何使用新函數執行相同的操作 pivot_*()
功能。
將寬格式轉換為長格式。
收集函數文件中的範例程式碼
# 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")
將長格式轉換為寬格式。
擴充函數文件中的範例程式碼
# old
stocks_spread <- stocks_gather %>% spread(key = stock,
value = price)
# new
stock_wide <- stocks_long %>% pivot_wider(names_from = "stock",
values_from = "price")
因為在上面的工作範例中 pivot_longer()
и pivot_wider()
,在原表中 股票 參數中未列出任何列 姓名_to и 值_to 他們的名字必須用引號引起來。
一張表格將幫助您最輕鬆地了解如何改用新概念 蒂德爾.
作者註
下面的所有文字都是自適應的,我甚至會說免費翻譯
小插圖 來自 tidyverse 圖書館官方網站。
將資料從寬格式轉換為長格式的簡單範例
pivot_longer ()
— 透過減少列數並增加行數來使資料集更長。
要運行本文中提供的範例,您首先需要連接必要的套件:
library(tidyr)
library(dplyr)
library(readr)
假設我們有一個表格,其中包含一項調查結果(除其他外)詢問人們的宗教信仰和年收入:
#> # 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>
表格依行包含受訪者的宗教數據,收入水準分散在各列名稱中。每個類別的受訪者數量儲存在宗教和收入水平交叉點的單元格值中。為了使表格變得整齊、正確的格式,使用就足夠了 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
函數參數 pivot_longer()
- 第一個論點 項圈,描述需要合併哪些欄位。在這種情況下,除 時間.
- 爭論 姓名_to 給出將從我們連接的列的名稱創建的變數的名稱。
- 值_to 給出將從儲存在合併列的儲存格值中的資料建立的變數的名稱。
產品規格
這是該套件的新功能 蒂德爾,以前在使用遺留函數時不可用。
規範是一個資料框,其每一行對應於新輸出日期框架中的一列,以及兩個以以下開頭的特殊列:
- 。名稱 包含原始列名稱。
- 。價值 包含將包含單元格值的資料列的名稱。
規範的其餘列反映了新列將如何顯示壓縮列的名稱 。名稱.
規範描述了以列名儲存的元數據,每列一行,每個變數一列,與列名結合起來,這個定義目前看起來可能很混亂,但是看了幾個例子就會變得很多更清晰。
該規範的要點是您可以檢索、修改和定義正在轉換的資料幀的新元資料。
若要在將表格從寬格式轉換為長格式時使用規範,請使用該函數 pivot_longer_spec()
.
該函數的工作原理是,它採用任何日期框架並以上述方式產生其元資料。
作為範例,我們以套件中提供的 who 資料集為例 蒂德爾。此資料集包含國際衛生組織提供的結核病發病率的資訊。
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
讓我們建構它的規範。
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
領域 國家, iso2, iso3 已經是變數。我們的任務是翻轉列 新_sp_m014 上 newrel_f65.
這些列的名稱儲存以下資訊:
- 字首
new_
表示該列包含有關結核病新病例的數據,當前日期範圍僅包含有關新疾病的信息,因此當前上下文中的此前綴不具有任何含義。 sp
/rel
/sp
/ep
描述了一種診斷疾病的方法。m
/f
患者的性別。014
/1524
/2535
/3544
/4554
/65
患者年齡範圍。
我們可以使用函數拆分這些列 extract()
使用正規表示式。
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
請注意欄目 。名稱 應保持不變,因為這是我們對原始資料集的列名稱的索引。
性別和年齡(列 性別 и 年齡)具有固定且已知的值,因此建議將這些列轉換為因子:
spec <- spec %>%
mutate(
gender = factor(gender, levels = c("f", "m")),
age = factor(age, levels = unique(age), ordered = TRUE)
)
最後,為了將我們創建的規範應用到原始日期範圍 誰 我們需要使用一個參數 規格 在功能上 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
我們剛才所做的一切可以示意性地描述如下:
使用多個值的規範(.value)
在上面的例子中,規格欄 。價值 僅包含一個值,大多數情況都是這種情況。
但有時,當您需要從值中具有不同資料類型的資料列收集資料時,可能會發生這種情況。使用遺留函數 spread()
這很難做到。
下面的例子摘自
讓我們建立一個訓練資料框。
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
建立的日期範圍在每一行中包含一個家庭的孩子的資料。家庭可能有一兩個孩子。對於每個孩子,提供了出生日期和性別的數據,並且每個孩子的數據位於單獨的列中;我們的任務是將這些數據轉換為正確的格式以進行分析。
請注意,我們有兩個變數包含每個孩子的資訊:性別和出生日期(帶有前綴的列 洗禮 包含出生日期,帶有前綴的列 性別 包含孩子的性別)。預期的結果是它們應該出現在單獨的列中。我們可以透過產生一個規範來做到這一點,其中列 .value
將有兩種不同的意義。
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
那麼,讓我們一步一步看看上面程式碼執行的操作。
pivot_longer_spec(-family)
— 建立壓縮除族列之外的所有現有列的規格。separate(col = name, into = c(".value", "child"))
- 拆分列 。名稱,其中包含來源欄位的名稱,使用下劃線並將結果值輸入到列中 。價值 и 孩子.mutate(child = parse_number(child))
— 轉換欄位值 孩子 從文字資料類型到數字資料類型。
現在我們可以將產生的規範應用到原始資料幀並將表格轉換為所需的形式。
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
我們使用論證 na.rm = TRUE
,因為資料的當前形式強制為不存在的觀測值建立額外的行。因為家庭2只有一個孩子, na.rm = TRUE
保證系列 2 將在輸出中包含一行。
將日期幀從長格式轉換為寬格式
pivot_wider()
- 是逆變換,反之亦然,透過減少行數來增加日期方塊的列數。
這種轉換很少用於將資料轉換為準確的形式,但是,這種技術對於建立簡報中使用的資料透視表或與某些其他工具整合非常有用。
其實功能 pivot_longer()
и pivot_wider()
是對稱的,並且產生彼此相反的作用,即: df %>% pivot_longer(spec = spec) %>% pivot_wider(spec = spec)
и df %>% pivot_wider(spec = spec) %>% pivot_longer(spec = spec)
將返回原始 df。
將表格轉換為寬格式的最簡單範例
演示該功能如何運作 pivot_wider()
我們將使用數據集 魚的遭遇,它儲存有關不同站點如何記錄魚類沿河運動的資訊。
#> # 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
在大多數情況下,如果您在單獨的列中提供每個網站的信息,則此表將提供更多資訊且更易於使用。
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>
此資料集僅記錄該站檢測到魚時的信息,即如果某個站沒有記錄任何魚類,則該資料將不會出現在表中。這意味著輸出將被 NA 填充。
然而,在這種情況下,我們知道沒有記錄意味著沒有看到魚,所以我們可以使用參數 值填充 在功能上 pivot_wider()
並用零填充這些缺失值:
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>
從多個來源變數產生列名
假設我們有一個包含產品、國家/地區和年份組合的表。若要產生測試日期範圍,您可以執行以下程式碼:
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
我們的任務是擴展資料框架,以便一列包含產品和國家/地區每種組合的資料。為此,只需傳入參數即可 姓名_來自 包含要合併的欄位名稱的向量。
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
您也可以將規範應用於函數 pivot_wider()
。但當提交給 pivot_wider()
規範進行相反的轉換 pivot_longer()
: 中指定的列 。名稱,使用來自的值 。價值 和其他專欄。
對於此資料集,如果您希望每個可能的國家/地區和產品組合都有自己的資料列,而不僅僅是資料中存在的列,則可以產生自訂規格:
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
使用新 tidyr 概念的幾個高級範例
以美國人口普查收入和租金資料集為例清理資料。
數據集 我們的租金收入 包含 2017 年美國每個州的中位數收入和租金資訊(資料集可在包中找到) 整理人口普查).
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
資料在資料集中儲存的形式 我們的租金收入 使用它們非常不方便,因此我們想要建立一個包含列的資料集: 租, 租_萌, 如何, 收入_教育部。創建這個規範的方法有很多,但重點是我們需要產生變數值和變數的每種組合 估計/教育部然後產生列名。
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
提供本規範 pivot_wider()
給了我們我們正在尋找的結果:
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
世界銀行
有時將資料集轉換為所需的形式需要幾個步驟。
數據集 世界銀行流行音樂 包含世界銀行 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>
我們的目標是建立一個整潔的資料集,每個變數都在自己的列中。目前尚不清楚到底需要採取哪些步驟,但我們將從最明顯的問題開始:年份分佈在多個欄位中。
為了解決這個問題,您需要使用該功能 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
下一步是查看指示變數。
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 是人口成長,SP.POP.TOTL 是總人口,SP.URB。 * 同樣的事情,但僅適用於城市地區。讓我們將這些值分為兩個變數:面積 - 面積(總面積或城市面積)和一個包含實際資料(人口或成長)的變數:
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
現在我們要做的就是將變數分成兩列:
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
聯絡人列表
最後一個例子,假設您有一個從網站複製並貼上的聯絡人清單:
contacts <- tribble(
~field, ~value,
"name", "Jiena McLellan",
"company", "Toyota",
"name", "John Smith",
"company", "google",
"email", "[email protected]",
"name", "Huxley Ratcliffe"
)
將此清單製成表格非常困難,因為沒有變數可以識別哪些資料屬於哪個聯絡人。我們可以透過注意每個新聯絡人的資料以「name」開頭來解決此問題,因此我們可以建立一個唯一標識符,並在每次欄位列包含值「name」時將其加一:
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
現在我們為每個聯絡人都有了唯一的 ID,我們可以將欄位和值轉換為列:
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>
結論
我個人的看法是新觀念 蒂德爾 真正更加直觀,並且在功能上明顯優於傳統功能 spread()
и gather()
。我希望這篇文章能幫助你解決 pivot_longer()
и pivot_wider()
.
來源: www.habr.com