R语言_table()函数与因子变量

1 出现问题


今天在写一个求众数的函数,思路很简单:统计unique数值,并计算其频数,取最大值就是,函数如下:

head(ani, 10)
   X0
1   0
2   0
3   0
4   0
5   0
6   0
7   0
8   0
9   0
10  0

getmode = function(v) {
  a = data.frame(table(v))
  b = max(a$Freq)
  c = a[which(a$Freq == b),] 
  return(c[1,1])
}

getmode(ani$X0)
[1] 0
6163 Levels: 0 0.029 0.03 0.032 0.033 0.036 0.044 0.045 0.048 0.054 0.057 0.058 0.06 0.064 0.065 0.068 ... 42.386

众数值没有问题,但是此处出现了因子水平levels,函数最后一步提取的应该是[1,1]位置的数值才对。怎么出现因子水平呢???

首先检验下众数

table(ani$X0)

    0 0.029  0.03 0.032 0.033 0.036 0.044 0.045 0.048 0.054 0.057 0.058  0.06 0.064 0.065 0.068 0.072 0.073 0.077 
 1371     4     1     1     1     1     1     1     1     1     2     1     1     1     1     1     1     1     3 
0.081 0.082 0.083 0.084 0.085 0.086 0.087 0.088 0.089  0.09 0.091 0.092 0.093 0.094 0.095 0.097 0.098   0.1 0.101 
    2     1     2     1     1     3     1     1     2     3     5     2     3     3     6    11     5     5     2 
0.102 0.103 0.105 0.107  0.11 0.114 0.116 0.117 0.118 0.119  0.12 0.121 0.122 0.125 0.128 0.129  0.13 0.132 0.134 
    1     1     1     3     1     2     1     2     1     1     3     2     1     1     2     3     1     1     1 
0.135 0.136  0.14 0.145 0.147  0.15 0.151 0.152 0.153 0.154 0.155 0.156 0.157 0.158 0.159  0.16 0.162 0.163 0.164 
    1     1     2     2     1     1     1     1     1     7     1     2     3     2     1     2     1     2     1 
0.165 0.166 0.167 0.168 0.169  0.17 0.171 0.172 0.173 0.174 0.175 0.176 0.177 0.178  0.18 0.181 0.183 0.184 0.185 
    1     1     1     3     1     3     2     2     3     2     2     2     2     1     1     1     2     3     1 
0.186 0.187 0.188 0.189  0.19 0.191 0.192 0.193 0.194 0.195 0.196 0.197 0.198 0.199   0.2 0.201 0.202 0.203 0.204 
...
 [ reached getOption("max.print") -- omitted 5163 entries ]

max( table(ani$X0))
[1] 1371      # 0出现次数最大 1371

2 问题关键:table()函数


问题出现在table函数上,table函数作用就是统计一组向量中unique元素的数量,具体参数请参照R帮助文件。R中这样解释table函数 , “table uses the cross-classifying factors to build a contingency table of the counts at each combination of factor levels”。 因此,table()返回的结果是带有因子水平的。

e = data.frame(table(ani$X0))

str(e)   # 注意变量Var1
'data.frame':   6163 obs. of  2 variables:
$ Var1: Factor w/ 6163 levels "0","0.029","0.03",..: 1 2 3 4 5 6 7 8 9 10 ...
$ Freq: int  1371 4 1 1 1 1 1 1 1 1 ...

这时候,当然想把因子变量转换成数值变量, as.numeric(), 这时候神奇的事情发生了:

head(as.numeric(e$Var1), 100)
  [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27
 [28]  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54
 [55]  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81
 [82]  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100

head(as.integer(e$Var1), 100)
  [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27
 [28]  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54
 [55]  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81
 [82]  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100

# 这完全不是原始值 
table(ani$X0)

3 因子变量


此处呼叫万能的网友,知乎博主[醉一心],CSDN博主[YaoRaoLov]给出了答案。参照以下博文:
https://zhuanlan.zhihu.com/p/147799787
https://ask.csdn.net/questions/707550?sort=comments_count

a.因子变量3个重要特征

  • 因子变量的有序性
  • 因子变量本质上是由数值型变量构成的
  • 因子变量取值的有限性

再来看下table()返回的数据框e

unclass(e$Var1[1:30])
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
attr(,"levels")
   [1] "0"     "0.029" "0.03"  "0.032" "0.033" "0.036" "0.044" "0.045" "0.048" "0.054" "0.057" "0.058" "0.06" 
  [14] "0.064" "0.065" "0.068" "0.072" "0.073" "0.077" "0.081" "0.082" "0.083" "0.084" "0.085" "0.086" "0.087"
  [27] "0.088" "0.089" "0.09"  "0.091" "0.092" "0.093" "0.094" "0.095" "0.097" "0.098" "0.1"   "0.101" "0.102"
  [40] "0.103" "0.105" "0.107" "0.11"  "0.114" "0.116" "0.117" "0.118" "0.119" "0.12"  "0.121" "0.122" "0.125"
  ...
 [ reached getOption("max.print") -- omitted 5163 entries ]

因子型变量在unclass()函数的作用下,显示出真面目:原来就是一个个数值型变量
这也就是为什么对其进行数值型转化时会得到1,2,3,4等一系列数值的原因。
它的真实值存储在Levels里面

b.因子变量的存储方式

  • 对于非因子向量,R需要存储其所有元素的每一个取值。
  • 对于因子型变量,R则存储其对应的水平的次序及有限的几个levels取值
x = sample(c("Apple", "Orange", "melon"), 100000, replace = TRUE)
head(x, 50)
 [1] "Apple"  "Orange" "Orange" "melon"  "Apple"  "Orange" "melon"  "melon"  "Orange" "melon"  "Apple"  "Orange"
[13] "melon"  "Apple"  "melon"  "Apple"  "Apple"  "Orange" "Orange" "melon"  "Orange" "melon"  "melon"  "Apple" 
[25] "Apple"  "Orange" "melon"  "melon"  "Orange" "melon"  "Orange" "Orange" "Orange" "Apple"  "Orange" "Apple" 
[37] "Apple"  "Orange" "Apple"  "Orange" "Orange" "melon"  "Apple"  "Orange" "melon"  "melon"  "Apple"  "melon" 
[49] "Apple"  "melon" 

y = as.factor(x)
head(y,50)  # 此处显示的文本内容,但是实际上还是数值,unclass()查看 
 [1] Apple  Orange Orange melon  Apple  Orange melon  melon  Orange melon  Apple  Orange melon  Apple  melon 
[16] Apple  Apple  Orange Orange melon  Orange melon  melon  Apple  Apple  Orange melon  melon  Orange melon 
[31] Orange Orange Orange Apple  Orange Apple  Apple  Orange Apple  Orange Orange melon  Apple  Orange melon 
[46] melon  Apple  melon  Apple  melon 
Levels: Apple melon Orange

# 减少了一半的存储空间
pryr::object_size(x) 
800,216 B
pryr::object_size(y) 
400,632 B

4 解决方法


  • method1 :将因子变量首先转换成字符串变量,然后再转换成数值变量
as.numeric(as.character(e$Var1)) 
head(as.numeric(as.character(e$Var1)) , 50)
 [1] 0.000 0.029 0.030 0.032 0.033 0.036 0.044 0.045 0.048 0.054 0.057 0.058 0.060 0.064 0.065 0.068 0.072 0.073
[19] 0.077 0.081 0.082 0.083 0.084 0.085 0.086 0.087 0.088 0.089 0.090 0.091 0.092 0.093 0.094 0.095 0.097 0.098
[37] 0.100 0.101 0.102 0.103 0.105 0.107 0.110 0.114 0.116 0.117 0.118 0.119 0.120 0.121
  • method2: 直接从Levels中提取数值变量
as.numeric(levels(e$Var1)[e$Var1])    # 同上

上述众数函数修改为下

getmode = function(v) {
  a = data.frame(table(v))
  b = max(a$Freq)
  c = a[which(a$Freq == b),] 
  return(as.numeric(as.character(c[1,1])))
}

getmode(ani$X0)
[1] 0

class(getmode(ani$X0))
[1] "numeric"
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容