左手用R右手Python系列——因子變數與分類重編碼
今天這篇介紹數據類型中因子變數的運用在R語言和Python中的實現。
因子變數是數據結構中用於描述分類事物的一類重要變數。其在現實生活中對應著大量具有實際意義的分類事物。
比如年齡段、性別、職位、愛好,星座等。
之所以給其單獨列出一個篇幅進行講解,除了其在數據結構中的特殊地位之外,在數據可視化和數據分析與建模過程中,因子變數往往也承擔中描述某一事物重要維度特徵的作用,其意義非同尋常,無論是在數據處理過程中還是後期的分析與建模,都不容忽視。
通常意義上,按照其所描述的維度實際意義,因子變數一般又可細分為無序因子(類別之間沒有特定順序,水平相等)和有序因子(類別中間存在某種約定俗成的順序,如年齡段、職稱、學歷、體重等)。
在統計學中對變數進行了如下四類劃分:定類變數、定序變數、定距變數、定比變數。而其中的定類和定比變數就對應著我們今天將要講解的因子變數(無序因子和有序因子變數)。
因子變數從信息含量上來看,其要比單純的定性變數(文本變數)所包含的描述信息多一些,但是又比數值型變數(定距變數和定比變數)所表述的信息含量少一些。
因而原則上來講,數值型變數可以轉換為因子變數,因子變數可以轉換為文本型變數,但是以上順序卻是不可逆的(信息含量多的變數可以放棄信息量,轉換為信息含量較少的變數類型,但是信息含量較少的變數卻無法增加信息含量)。
以下將分別講解在R語言和Python中如何生成因子變數、如何將數值型變數轉換為因子變數、以及如何對因子變數進行重編碼。
在R語言中,通常使用factor直接生成因子變數,我們僅需一個向量(原則上可以是文本型、也可以是數字型,但是通常從實際意義上來說,被轉換的應該是一個含有多類別的類別型文本變數)。
factor(x, levels,labels=levels,ordered=)
以上參數中,x即是我們將要轉換的變數,levels是將要設定的因子水平(可選參數,省略則自動以向量中的不重複對象為因子水平),labels作為因子標籤(可選參數,與前述因子水平對應,若設置,則列印時顯示的是對應因子標籤,省略則同因子水平一樣,使用向量中不重複值【即類別】作為標籤),ordered是邏輯參數,設定是否對因子水平排序。
vector<-rep(LETTERS[1:5],6);print(vector);plyr::count(vector)myfactor<-(factor(vector,levels=c("E","D","C","B","A"),labels=c("EEE","DDD","CCC","BBB","AAA"),ordered=TRUE)
通常來說,factor函數中,levels一般不用設置,函數會自動判斷向量內有幾個水平,但是倘若要生成有序因子的話,默認會根據字母順序排列,如果自然順序與目標有序因子順序不一致,則一定要指定levels,labels則視具體需求而定,如果本身就是文本類別的話,一般無需設定標籤。
如果是問卷類數據,而且編碼為數值,則一定要通過labels標籤的設定來還原每一個編碼的真實意義。
factor(vector,labels=c("AAA","BBB","CCC","DDD","EEE"),ordered=TRUE)
因子變數與文本變數數值變數之間的互轉則通過as.character()或者as.numeric()函數來實現。
library(dplyr)as.character(as.factor(1:10))%>%str()as.numeric(as.factor(1:10))%>%str()
R語言中的因子變數重編碼
如果你有一個度量指標,需要將其轉換為分段的因子變數,則可以通過cut函數來實現這種轉換。
scale<-runif(100,0,100)cut(x,breaks,labels=NULL,include.lowest=FALSE,right=TRUE,ordered=)
cut函數參數如上,接受一個數值型向量,breaks接受一個數值向量(標識分割點)或者單個數值(分割 數目)。
right是邏輯參數,設定分割帶是左開右閉或者左閉右開。(默認左開右閉)。
include.lowest則根據right的設定,決定是否應該包含端點值(如果right為TRUE,左開右閉區間,則包含最小值,如果right為FALSE,左閉右開區間則包含最大值),默認為FALSE。
ordered則設定是否對因子水平進行排序。
(factor1<-cut(scale,breaks=c(0,20,40,60,80,100),labels=c("0~20","20~40","40~60","60~80","80~100"),include.lowest=TRUE,ordered=TRUE)
另一種分割場景是使用分位數函數進行分割。
qa <- quantile(scale, c(0,0.2,0.4,0.6,0.8,1.0))(cut(scale,breaks=qa,labels=c("0%~20%","20%~40%","40%~60%","60%~80%","80%~100%"),include.lowest=TRUE,ordered=TRUE))
以上分割方法在是較為常用的因子變數轉換方法,當然你可以使用if函數進行類似分割,但是相比較來講,使用cut函數進行分割要高效很多。
Python
在Python中,Pandas庫包含了處理因子變數的一整套完整語法函數。
import pandas as pdimport numpy as npimport string
在pandas中的官方在線文檔中,給出了pandas因子變數的詳細論述,並在適當位置與R語言進行了對比描述。
http://pandas.pydata.org/pandas-docs/stable/categorical.html#working-with-categories
當利用pandas生成序列時,可以在序列函數內的dtype參數設定因子變數類型。
s = pd.Series(["A","B","C","D","E"], dtype="category")
生成數據框時,也可以直接生成因子變數。
df = pd.DataFrame({"A":["a","b","c","a"]})df["B"] = df["A"].astype("category")
除了直接在生成序列或者數據框時生成因子變數之外,也可以通過一個特殊的函數pd.Categorical來完成在序列和數據框中創建因子變數。
s = pd.Series(pd.Categorical(["a","b","c","a"], categories=["a","b","c"],ordered=False))df = pd.DataFrame({"A":["a","b","c","a"]})df["B"] =pd.Series(pd.Categorical(["a","b","c","a"], categories=["a","b","c"],ordered=False))
因子順序的添加可以通過設定序列或者數框框列的.astype來進行詳細的操作。
s = pd.Series(["a","b","c","a"])s_cat = s.astype("category", categories=["a","b","c"], ordered=True)
無論是序列中還是數據框中的因子變數生成之後,都可以通過以下屬性查看其具體的類型、因子類別、以及是否含有順序。
- s_cat.dtypes
- s_cat.cat.categories
- s_cat.cat.ordered
一種比較迂迴的方法是,先生成普通序列,然後通過設定序列類型完成因子變數的轉化。而想要捨棄因子變數,還原成普通的文本序列,則同樣只需再其astype中進行格式設定。
s = pd.Series(["a","b","c","a"])s2 = s.astype("category",categories=["a","b","c"],ordered=True)s2.astype(str)
最後講一下,如何在數據框中分割數值型變數為因子變數,pandas的數據框也有與R語言同名的函數——cut。
df = pd.DataFrame({"value": np.random.randint(0, 100, 20)})labels = [ "{0} - {1}".format(i, i + 9) for i in range(0,100,10) ]df["group"] = pd.cut(df.value, range(0, 105, 10), right=False, labels=labels)
pd.cut(x, bins, right=, labels=,include_lowest=False)#df.value代表待風格的變數,第二項是bins可以是一個列表(作為分割點),也可以是一個整數(作為分割帶箱數),right控制帶寬是左開右閉還是左閉右開,labels設定輸出顯示標籤,include_lowest=控制是否包含邊界點(以上參數可以類比R語言中的cut函數)。
最後做一個小總結:
關於因子變數在R語言和Python中涉及到的操作函數;
R語言:
創建因子變數:
factor
轉換因子變數:
as.factor
as.numeric(as.character)
分割因子變數:
cut函數
Python:
創建因子變數:
pd.Categorical(categories=,ordered=)
pd.Series(dtype="category")
轉換因子變數:
df.astype("category",categories,ordered)
分割因子變數:
df.cut(df.value,breaks=,right=,labels)
微信:ljty1991
博客主頁:raindu's home
個人公眾號:數據小魔方(datamofang)
團隊公眾號:EasyCharts
qq交流群:[魔方學院]298236508
推薦閱讀:
※R for data science之purrr包(上)
※BI轉數據挖掘,我的脫產學習路
※七周成為數據分析師:Excel技巧:好用到哭的多級菜單
※YARN 分散式資源調度
※人工智慧和機器學習會逐漸取代金融和數據分析師嗎?