#使用forcats處理因子
#因子在 R 中用于處理分類變量。
#分類變量是在固定的已知集合中取值的變量。
#當(dāng)想要以非字母表順序顯示字符向量時,也可以使用分類變量。
library(tidyverse)
library(forcats)
#創(chuàng)建因子
#假設(shè)我們想要創(chuàng)建一個記錄月份的變量:
x1 <- c("Dec", "Apr", "Jan", "Mar")
#使用字符串來記錄月份有兩個問題。
#(1) 月份只有 12 個取值,如果輸入錯誤,那么代碼不會有任何反應(yīng)。
x2 <- c("Dec", "Apr", "Jam", "Mar")
#(2) 其對月份的排序沒有意義。
sort(x1)
#> [1] "Apr" "Dec" "Jan" "Mar"
#你可以通過使用因子來解決以上兩個問題。
#要想創(chuàng)建一個因子,必須先創(chuàng)建有效水平的一個列表:
month_levels <- c(
? "Jan", "Feb", "Mar", "Apr", "May", "Jun",
? "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
)
#現(xiàn)在你可以創(chuàng)建因子了:
y1 <- factor(x1, levels = month_levels)
y1
sort(y1)
#不在有效水平集合內(nèi)的所有值都會自動轉(zhuǎn)換為 NA:
y2 <- factor(x2, levels = month_levels)
y2
#如果想要顯示錯誤信息,那么你可以使用 readr::parse_factor() 函數(shù):
y2 <- parse_factor(x2, levels = month_levels)
#如果省略了定義水平的這個步驟,那么會將按字母順序排序的數(shù)據(jù)作為水平:
factor(x1)
#有時你會想讓因子的順序與初始數(shù)據(jù)的順序保持一致。
#在創(chuàng)建因子時,將水平設(shè)置為 unique(x),
#或者在創(chuàng)建因子后再對其使用 fct_inorder() 函數(shù),就可以達(dá)到這個目的:
f1 <- factor(x1, levels = unique(x1))
f1
#> [1] Dec Apr Jan Mar
#> Levels: Dec Apr Jan Mar
f2 <- x1 %>% factor() %>% fct_inorder()
f2
#> [1] Dec Apr Jan Mar
#> Levels: Dec Apr Jan Mar
#如果想要直接訪問因子的有效水平集合,那么可以使用 levels() 函數(shù):
levels(f2)
#> [1] "Dec" "Apr" "Jan" "Mar"
#綜合社會調(diào)查
# forcats::gss_cat 數(shù)據(jù)集,該數(shù)據(jù)集是綜合社會調(diào)查數(shù)據(jù)的一 份抽樣,
#綜合社會調(diào)查是美國芝加哥大學(xué)的獨(dú)立研究組織 NORC 進(jìn)行的一項長期美國社會調(diào)查
gss_cat
#當(dāng)因子保存在 tibble 中時,其水平不是很容易看到的。
#查看因子水平的一種方法是使用 count() 函數(shù):
gss_cat %>%
? count(race)
#或者使用條形圖
ggplot(gss_cat, aes(race)) +
? geom_bar()
#ggplot2 會丟棄沒有任何數(shù)據(jù)的那些水平,你可以使用以下代碼來強(qiáng)制顯示這些水平:
ggplot(gss_cat, aes(race)) + geom_bar() + scale_x_discrete(drop = FALSE)
#這些水平表示的也是有效值,只是沒有出現(xiàn)在這個數(shù)據(jù)集中。
#在使用因子時,最常用的兩種操作是修改水平的順序和水平的值。
#修改因子水平
#比修改因子水平順序更強(qiáng)大的操作是修改水平的值。
#修改水平最常用、最強(qiáng)大的工具是 fct_recode() 函數(shù),它可以對每個水平進(jìn)行修改或重新編碼。
#我們看一下 gss_cat$partyid:
gss_cat %>% count(partyid)
#對水平的描述太過簡單,而且不一致。
#fct_recode() 會讓沒有明確提及的水平保持原樣,
#如果不小心修改了一個不存在的水平, 那么它也會給出警告。
gss_cat %>% count(partyid)
#修改:新=舊,是按照賦值的思路
gss_cat %>%
? mutate(partyid = fct_recode(partyid,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Republican, strong" = "Strong republican",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Republican, weak" = "Not str republican",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Independent, near rep" = "Ind,near rep",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Independent, near dem" = "Ind,near dem",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Democrat, weak" = "Not str democrat",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Democrat, strong" = "Strong democrat"
? )) %>%
? count(partyid)
#這里用mutate進(jìn)行了覆蓋
#你可以將多個原水平賦給同一個新水平,這樣就可以合并原來的分類:
#查看數(shù)據(jù)框中某因子列的levels
#(看mutate最后三行)
gss_cat %>%
? mutate(partyid = fct_recode(partyid,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Republican, strong" = "Strong republican",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Republican, weak" = "Not str republican",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Independent, near rep" = "Ind,near rep",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Independent, near dem" = "Ind,near dem",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Democrat, weak" = "Not str democrat",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Democrat, strong" = "Strong democrat",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Other" = "No answer",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Other" = "Don't know",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Other" = "Other party"
? )) %>%
? count(partyid)
#使用這種操作時一定要小心:如果合并了原本不同的分類,那么就會產(chǎn)生誤導(dǎo)性的結(jié)果。
#如果想要合并多個水平,那么可以使用 fct_recode() 函數(shù)的變體 fct_collapse() 函數(shù)。
#對于每 個新水平,你都可以提供一個包含原水平的向量:
gss_cat %>%
? mutate(partyid = fct_collapse(partyid,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? other = c("No answer", "Don't know", "Other party"),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? rep = c("Strong republican", "Not str republican"),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ind = c("Ind,near rep", "Independent", "Ind,near dem"),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dem = c("Not str democrat", "Strong democrat")
? )) %>%
? count(partyid)