昨天做完信息熵計算之後,想到了一個問題
一般我們用read.csv讀取一個表格時,R軟件自動判斷轉換出來的分類型變量好像經常性的對不上我們的認知,大概舉個例子:
比如我現在讀取了一張表,沒附加參數,由R自行判斷哪些列可以作為分類變量轉成因子型
在它讀取完之後,我看了看它的轉化結果,然後在圖的左邊添了一列圈圈叉叉
其中×的那兩排,就是我的認知跟它有分歧的地方(表格總共9列)
這正確率還真是不太高,難怪很多書上都推薦加stringsAsFactor參數
但是,如果是個列數很多的大表格,我不用眼睛去人工判斷的話,有可能讓R軟件儘量自己分正確嘛?
然後,我萌生了做個表格轉換function的想法,併成功地把自己坑到了晚上10點還在整代碼的境地
從數學角度來說,判斷是否分類變量的依據大概是這樣的:
我們先計算出表中每列向量的熵值,由於這裡全部是單向量輸入,所以弄了個簡化版(跟昨天相比的話)
按照熵的性質,其取值範圍是個介於[0,log2(n)]的值,其中n為向量長度,那就是說,如果我把所有熵值都除以它的最大值,就可以統一轉換成一個0到1之間的量度了吧
算出比值後對照下我認知中的分類變量,可以看到符合要求的分類變量熵值都比較小,那怎麼判斷分類和連續的中間節點呢,這時我想到要不畫個圖看看
當用diff函數做一階差分後,感覺已經看到了勝利的曙光,咱要的分界節點就是一階差分的最大值,排在他前邊的判斷為分類項,在它本身和它之後的判斷為連續值
PS:diff做完會把向量剪短一個,所以做之前先多補了一個最小值進去
當數學部分差不多搞定後,我發現了另一個蛋疼的問題,那就是從來可以應對大部分循環結構的apply函數,失效了
是的,由於它在拆解二維表到向量的過程中已經內部轉換了一次向量格式到文本型,以至於它碰到所有判斷向量格式的函數一律回答character,所以,我默默地打開幫助文檔去撿回了丟棄已久的for函數
最終整理出來的完整代碼如下:
#單列熵值計算
En1 Pi En return(En) }
#判斷向量為分類還是連續
GCconvert if (!is.data.frame(x)){
stop("'x' must be data.frame") }
else{
Pi names(Pi) D1 Gcols for (i in 1:ncol(x)) {
if(is.factor(x[,i])) {
x[,i] }
for (j in Gcols) {
x[,j] }
return(x) }
當中為了避免表中已有被錯轉成因子型的列,增加了一段for循環轉成文本
代進去試下效果
嗯,有前途,後邊可以再多試幾個表看看 : )
閱讀更多 jennifer5jl 的文章