筆記說明
tidyr包是一個(gè)用于整理數(shù)據(jù)結(jié)構(gòu)的r包,也是tidyverse
的核心包之一。
本次筆記介紹tidy data、長(zhǎng)數(shù)據(jù)、寬數(shù)據(jù)的相關(guān)概念以及用于長(zhǎng)數(shù)據(jù)、寬數(shù)據(jù)相互轉(zhuǎn)換的函數(shù)。
推薦閱讀:
關(guān)于tidyr包:https://tidyr.tidyverse.org/
關(guān)于tidy data: https://tidyr.tidyverse.org/articles/tidy-data.html
tidy data論文:https://vita.had.co.nz/papers/tidy-data.html
關(guān)于長(zhǎng)寬數(shù)據(jù)轉(zhuǎn)換操作:https://tidyr.tidyverse.org/articles/pivot.html
長(zhǎng)數(shù)據(jù)、寬數(shù)據(jù)
同樣的數(shù)據(jù)內(nèi)容可以以不同的數(shù)據(jù)結(jié)構(gòu)呈現(xiàn)在數(shù)據(jù)集中。
我們用tidyr包自帶的示例數(shù)據(jù)集table4a來(lái)說明。
數(shù)據(jù)集table4a中的數(shù)據(jù)為三個(gè)國(guó)家1999和2000年的結(jié)核病例數(shù)
# 加載包
library(tidyr)
library(dplyr)
table4a
table4a
## # A tibble: 3 x 3
## country `1999` `2000`
## * <chr> <int> <int>
## 1 Afghanistan 745 2666
## 2 Brazil 37737 80488
## 3 China 212258 213766
為方便演示說明,我們新添一列2001年的數(shù)據(jù)(杜撰):
table_wide <- table4a %>%
mutate(`2001` = `1999` + `2000`)
## # A tibble: 3 x 4
## country `1999` `2000` `2001`
## <chr> <int> <int> <int>
## 1 Afghanistan 745 2666 3411
## 2 Brazil 37737 80488 118225
## 3 China 212258 213766 426024
同樣的數(shù)據(jù)內(nèi)容,還可以按下面的數(shù)據(jù)結(jié)構(gòu)來(lái)組成數(shù)據(jù)集table_long:
## # A tibble: 9 x 3
## country year case
## <chr> <chr> <int>
## 1 Afghanistan 1999 745
## 2 Afghanistan 2000 2666
## 3 Afghanistan 2001 3411
## 4 Brazil 1999 37737
## 5 Brazil 2000 80488
## 6 Brazil 2001 118225
## 7 China 1999 212258
## 8 China 2000 213766
## 9 China 2001 426024
- 像
table_wide
這樣,(同樣數(shù)據(jù)內(nèi)容下)變量多觀測(cè)少,通過ID(區(qū)分不同研究對(duì)象的變量,這里即為country變量)值和變量名來(lái)定位數(shù)據(jù)值的數(shù)據(jù)結(jié)構(gòu)稱為寬數(shù)據(jù)(wide format) - 像
table_long
這樣,(同樣數(shù)據(jù)內(nèi)容下)變量少觀測(cè)多,通過ID值和類別變量(這里即為year變量)值來(lái)定位數(shù)據(jù)值的數(shù)據(jù)結(jié)構(gòu)為長(zhǎng)數(shù)據(jù)(long format)
有些數(shù)據(jù)分析方法需要數(shù)據(jù)為寬數(shù)據(jù),而有些數(shù)據(jù)分析方法則要求數(shù)據(jù)為長(zhǎng)數(shù)據(jù)。因此對(duì)數(shù)據(jù)結(jié)構(gòu)進(jìn)行變換也是統(tǒng)計(jì)分析的基本功。另外,長(zhǎng)數(shù)據(jù)一般來(lái)說更方便進(jìn)行數(shù)據(jù)錄入以及數(shù)據(jù)比較。
tidy data和messy data
tidy data是Hadley Wickham提出的一種結(jié)構(gòu)化的數(shù)據(jù)集形式,它要求數(shù)據(jù)集滿足下列條件:
- Each variable forms a column. 每個(gè)變量形成一列
- Each observation forms a row. 每個(gè)觀測(cè)形成一行
- Each type of observational unit forms a table. 每種類型的觀測(cè)的單元形成一張表
所有不滿足tidy data條件的數(shù)據(jù)集都是messy data。所謂tidy data全都相似,而messy data各有不同。違背tidy data條件的最常見的幾種情形:
- Column headers are values, not variable names.
- Multiple variables are stored in one column.
- Variables are stored in both rows and columns.
- Multiple types of observational units are stored in the same table.
- A single observational unit is stored in multiple tables.
第一種情形:Column headers are values, not variable names.列名是變量值而不是變量名。需要對(duì)數(shù)據(jù)進(jìn)行寬數(shù)據(jù)向長(zhǎng)數(shù)據(jù)的轉(zhuǎn)換以變?yōu)閠idy data。以剛才展示的table_wide和table_long為例,table_long符合tidy data的要求,而table_wide就是messy data,因?yàn)樗牧忻?code>1999 2000
2001
應(yīng)該視為變量值而非變量名。
實(shí)際中區(qū)分列名是變量值還是變量名有時(shí)候是比較模糊的??梢越Y(jié)合不同列是否橫向可加來(lái)判斷,如果橫向可加則考慮列名是變量值。
第二種情形:Multiple variables are stored in one column.多個(gè)變量存儲(chǔ)于同一列。需要對(duì)數(shù)據(jù)進(jìn)行長(zhǎng)數(shù)據(jù)向?qū)挃?shù)據(jù)的轉(zhuǎn)換以變?yōu)閠idy data。例如:
## # A tibble: 4 x 3
## id variable vlaue
## <dbl> <chr> <dbl>
## 1 1 身高 170
## 2 1 體重 65
## 3 2 身高 178
## 4 2 體重 73
該數(shù)據(jù)中value列其實(shí)包含了身高、體重兩個(gè)變量的值。判斷一列內(nèi)是否存在多個(gè)變量,可以結(jié)合該列是否縱向可加來(lái)判斷,如果不可加則考慮存在多個(gè)變量。
用pivot_longer()將寬數(shù)據(jù)轉(zhuǎn)為長(zhǎng)數(shù)據(jù)
pivot_longer()
使寬數(shù)據(jù)轉(zhuǎn)換為長(zhǎng)數(shù)據(jù)。其簡(jiǎn)要用法為:
pivot_longer(data, cols, names_to = "name", values_to = "value")
-
data
即為需要進(jìn)行數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)化的數(shù)據(jù)集 -
col
指定進(jìn)行轉(zhuǎn)化的列,在select()
函數(shù)中可以幫助指定列的"select helper"在這里也適用,可以使用負(fù)號(hào)“-”表示反向選擇。 -
names_to
:col
指定的那些列的列名會(huì)組成一個(gè)新的變量,names_to
指定該新變量的變量名 -
values_to
:col
指定的那些列的變量值會(huì)組成一個(gè)新的變量,values_to
指定該新變量的變量名
舉例:把table_wide轉(zhuǎn)變?yōu)閠able_long:
## # A tibble: 3 x 4
## country `1999` `2000` `2001`
## <chr> <int> <int> <int>
## 1 Afghanistan 745 2666 3411
## 2 Brazil 37737 80488 118225
## 3 China 212258 213766 426024
table_long <- table_wide %>%
pivot_longer(cols = -country, names_to = "year", values_to = "case")
## # A tibble: 9 x 3
## country year case
## <chr> <chr> <int>
## 1 Afghanistan 1999 745
## 2 Afghanistan 2000 2666
## 3 Afghanistan 2001 3411
## 4 Brazil 1999 37737
## 5 Brazil 2000 80488
## 6 Brazil 2001 118225
## 7 China 1999 212258
## 8 China 2000 213766
## 9 China 2001 426024
pivot_longer()與gather()
pivot_longer()
函數(shù)是之前的版本中gather()
函數(shù)的改良。雖然新版本仍然保留了gather()
函數(shù),但建議寫新代碼時(shí)使用pivot_longer()
而不是gather()
對(duì)于使用過gather()
的用戶,以下兩條代碼是等價(jià)的。
df %>% gather("key", "value", x, y, z)
df %>% pivot_longer(c(x, y, z), names_to = "key", values_to = "value")
用pivot_wider()將長(zhǎng)數(shù)據(jù)轉(zhuǎn)為寬數(shù)據(jù)
pivot_wider()
使長(zhǎng)數(shù)據(jù)轉(zhuǎn)換為寬數(shù)據(jù)。其簡(jiǎn)要用法為:
pivot_wider(data, id_cols = NULL, names_from = name,values_from = value,)
-
data
即為需要進(jìn)行數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)化的數(shù)據(jù)集 -
id_cols
指定用什么變量來(lái)識(shí)別不同觀測(cè)。不指定時(shí)默認(rèn)用除names_from
和values_from
所指定變量之外的所有變量來(lái)識(shí)別不同觀測(cè)。 -
names_from
指定新數(shù)據(jù)集中展開的各新變量的變量名由舊數(shù)據(jù)集的哪個(gè)(或哪些)變量得到 -
values_from
指定新數(shù)據(jù)集中展開的各新變量的變量值由舊數(shù)據(jù)的哪個(gè)(或哪些)得到。如果指定了多個(gè)值,則會(huì)求和得到新變量值。
舉例:將table_long變回寬數(shù)據(jù):
table_long %>% pivot_wider(id_cols = country, names_from = year, values_from = case)
(實(shí)際上id_cols可以不寫,我個(gè)人習(xí)慣寫一下)
## # A tibble: 3 x 4
## country `1999` `2000` `2001`
## <chr> <int> <int> <int>
## 1 Afghanistan 745 2666 3411
## 2 Brazil 37737 80488 118225
## 3 China 212258 213766 426024
pivot_wider()與spread()
pivot_wider()
函數(shù)是之前的版本中spread()
函數(shù)的改良。雖然新版本仍然保留了spread()
函數(shù),但建議寫新代碼時(shí)使用pivot_wider()
而不是spread()
對(duì)于使用過spread()
的用戶,以下兩條代碼是等價(jià)的。
df %>% spread(key, value)
df %>% pivot_wider(names_from = key, values_from = value)