因子型数据是R语言中非常重要的一种数据类型,主要用于分组。本文主要分为两个部分:怎样用R语言从技术层面上对因子型数据进行处理;因子型数据的用途。前者我们将分别使用基础函数和forcats包进行讲述,后者只列出我目前想到的几个方面,以后想到其他的会再往里面补充。
本文目录如下
-
基础函数
-
forcats包
-
factor的使用
-
分组计算、统计分析与绘图
-
一个标签汇总问题
-
将定序变量转化为哑变量
基础函数
针对因子型数据,我们一般需要用到两种变化
-
更改level标签名
-
更改level顺序
我们先使用基础函数实现
(f1 <- factor(c(1,3,5,4,7))) # levels 中只有出现过的 # [1] 1 3 5 4 7 # Levels: 1 3 4 5 7 (f2 <- factor(c(1,3,5,4,7), levels=1:10)) # 指定有哪些levels # [1] 1 3 5 4 7 # Levels: 1 2 3 4 5 6 7 8 9 10 factor(c(1,3,5,4,7), levels=1:10, labels=letters[1:10]) # 给各个levels命名 # [1] a c e d g # Levels: a b c d e f g h i j f2[, drop=T] # 去掉未出现过的levels # 下面对原有的factor进行变化 # 使用levels函数更改level标签名 levels(f1) # 查看f1的levels有哪些 # [1] "1" "3" "4" "5" "7" levels(f1)[1] <- "x" # 修改第一个level为x,level和向量内容都跟着改变了 f1 # [1] x 3 5 4 7 # Levels: x 3 4 5 7 levels(f1)[2] <- "x" # 将一二两个level合并成一个x f1 # [1] x x 5 4 7 # Levels: x 4 5 7 levels(f1)[4] <- "x" # 注意这时改变的是新的f1的第4个,即对应7的level f1 # [1] x x 5 4 x # Levels: x 4 5 # 修改levels顺序,经常用于数据框中一列factor的自身变化 (f1 <- factor(c(1,3,5,4,7))) # 默认按照数字大小顺序排列 f1 <- factor(f1, levels=rev(f1)) # 将原来levels颠倒,不改变向量内容 f1 # [1] 1 3 5 4 7 # Levels: 7 4 5 3 1 # 注意下面这种写法 (f1 <- factor(c(1,3,5,4,7))) levels(f1) <- rev(levels(f1)) f1 # [1] 7 5 3 4 1 # Levels: 7 5 4 3 1 # 变化的是标签名,没有真正改变顺序
forcats包更方便地处理factor,其实就是使用基础包中的函数,实现一些特定的功能,封装成一个包,让人们需要用的时候可以简单地调用,不用自己再编写函数了。
其中的函数分为如下几类
1.修改levels顺序的函数,向量内元素不变 fct_relevel 指定某个level移动到特定位置 fct_inorder 按照第一次出现的次序排列 fct_infreq 按照出现的频率排列 fct_reorder 和 fct_reorder2 作用在一个数据框中的一列factor上,他们的 排序 要依赖其他列的值 fct_shuffle 随机排序 fct_rev 倒序 fct_shift 实现前后移动,滚动变化 2.变换levels名称的函数 fct_anon 用有规律的数字表示 fct_collapse 对应指定更改,主要用于多个合并成一个 fct_recode 手动更改 fct_lump 将出现次数较少的设置为"other" fct_other 将指定的 level 设置成"other" fct_relabel 在原有基础上进行修改 3.其他函数 fct_c 将两个factor结合 fct_count 数每一个 level 的数量 fct_unique 让每一个level只有一个 fct_drop 去掉一些levels (下面三个更一般的函数,上面这些函数都有着特定的功能,基本上都是调用下面这三个函数实现的) lvls_reorder 更改level顺序 lvls_revalue 整体更改level名称 lvls_expand 增加一个level
因为这个包只涉及到比较简单的使用,所以下面很多代码是直接从帮助文档中扒下来的
1.修改level顺序的函数使用
# 改变levels顺序 library(forcats) library(ggplot2) f <- factor(c("a", "b", "c", "d")) fct_relevel(f) # 查看原本的f fct_relevel(f, "c") # c移动到第一位 fct_relevel(f, "b", "a") # b a 移动到前两位 fct_relevel(f, "a", after = 2) # a往后移动两位 fct_relevel(f, "a", after = Inf) # a移动到最后,常用语把像“不知道"z这样的移到最后 f <- factor(c("b", "b", "a", "c", "c", "c")) fct_inorder(f) # 按照第一次出现的次序排列 fct_infreq(f) # 按照出现的频率排列 # 按照每一组Sepal.Width的均值从小到大排列 boxplot(Sepal.Width ~ fct_reorder(Species, Sepal.Width, median), data = iris) boxplot(Sepal.Width ~ fct_reorder(Species, Sepal.Width, median, .desc=T), data = iris) # 从大到小 # 按照每一组time的最后一个值,对应的weight的大小顺序排列 chks <- subset(ChickWeight, as.integer(Chick) < 10) chks <- transform(chks, Chick = fct_shuffle(Chick)) ggplot(chks, aes(Time, weight, colour = fct_reorder2(Chick, Time, weight))) + geom_point() + geom_line() + labs(colour = "Chick") # 随机排序 f <- factor(c("a", "b", "c")) fct_shuffle(f) fct_shuffle(f) # 倒序 f <- factor(c("a", "b", "c")) fct_rev(f) # 前后移动,滚动变化 fct_shift(f) # 第一项放到最后 fct_shift(f, 2) # 前两项放在最后 fct_shift(f, -1) # 最后一项移到最前面
2.修改level标签的函数使用
f <- factor(c("b", "b", "a", "c", "c", "c")) fct_anon(f) fct_anon(f, "x") fct_collapse(f, "x"=c("a","b"), "y"="c") fct_collapse(f, "x"=c("a","b")) # 只改变一部分也可以 x <- factor(rep(LETTERS[1:9], times = c(40, 10, 5, 27, 1, 1, 1, 1, 1))) x %>% table() x %>% fct_lump() %>% table() x <- factor(letters[rpois(100, 5)]) x table(x) table(fct_lump(x)) # Use positive values to collapse the rarest table(fct_lump(x, n = 4)) # 保留4个最多的level,其他的进入other table(fct_lump(x, prop = 0.1)) # 保留数量超过10%的level # Use negative values to collapse the most common table(fct_lump(x, n = -3)) # 保留最少的3个 table(fct_lump(x, prop = -0.1)) # 保留数量少于10%的 fct_lump(x, n = 6, ties.method = "max") # 更换计算方法 # 有这些种选择:ties.method = c("min","average", "first", "last", "random", "max") table(fct_lump(x, n = 4, other_level = "another")) # 更改替换名称 # 将指定的level设置成other x <- factor(rep(LETTERS[1:9], times = c(40, 10, 5, 27, 1, 1, 1, 1, 1))) fct_other(x, keep = c("A", "B")) # 保留这两个 fct_other(x, drop = c("A", "B")) # 把这两个变成other # 手动更改 x <- factor(c("apple", "bear", "banana", "dear")) fct_recode(x, fruit = "apple", fruit = "banana") fct_recode(x, NULL = "apple", fruit = "banana") # 移除level,向量对应位置变成NA # 在原有基础上进行修改 x <- factor(c("apple", "bear", "banana", "dear")) f <- function(i){ paste(i,1:4,sep="") } fct_relabel(x,f)
3.其他函数
fa <- factor("a") fb <- factor("b") fab <- factor(c("a", "b")) # 多个factor结合成一个 c(fa, fb, fab) # 变成了一个向量 fct_c(fa, fb, fab) fct_c(list(fa, fb, fab)) # 或者这样 # 对每一个level计数 f <- factor(c("b", "b", "a", "c", "c", "c")) fct_count(f) # 将多个factor结合到一个list中 fs <- list(factor("a"), factor("b"), factor(c("a", "b"))) fs # 直接转化的list各自levels不一样 fct_unify(fs) # 结合之后levels统一了 # 唯一化 unique(f) fct_unique(f) # 向量中元素按照level的顺序排列 f <- factor(c("a", "b"), levels = c("a", "b", "c")) f fct_drop(f) # 默认将没有对应值的level去掉 fct_drop(f, only = "a") # 如果a不对应则去掉,其他的不要管 fct_drop(f, only = "c") fct_drop(f, only = c("a","c")) # 在这个向量里面的元素如果有不对应的,就去掉,其他不要管 f <- factor(c("a", "b", "c")) lvls_reorder(f, c(2,3,1)) # 原来第二个放在第一个,原来第三个放在第二个,原来第一个放在最后 lvls_revalue(f, c("apple", "banana", "carrot")) lvls_expand(f, c("a", "b", "c", "d"))
因子型数据的使用
1.分组计算、统计分析与绘图
library(data.table) library(ggplot2) df <- data.table(a = 1:20, b = sample(1:20,20), c = rep(1:5,4)) # 分组计算,以均值为例 df[, mean(b), by=c] df[, mean(b), by=factor(c)] # 上面这种分组计算是否转化成因子型其实都可以,但是在有的特定统计分析中,如果不转化为因子型就会输出错误的结果 x1 = c(-0.01, 0.15, 0.25, -0.90, 0.86) x2 = c(11.14, 9.56, 10.33, 8.45, 9.59) x3 = c(0.77, 0.03, 1.96, 3.24, 2.40) x = c(x1, x2, x3) grps =rep(1:3, each=5) summary(aov(x~grps)) # 得到错误的结果 summary(aov(x~factor(grps))) # 正确的做法 # 分组绘图,以条形图为例 ggplot(df,aes(a,b)) + geom_line(aes(color=factor(c))) # 这个也必须转化为因子型
2.一个标签汇总问题
比如我们拿到了一个数据集,有3个人列出自己喜欢的软件,但是数据格式不是很理想,我们要将其转化为我们想要的表格形式,具体如下
library(data.table) library(magrittr) ori_df <- data.table(name = c("a","b","c"), like = c("R|python", "python|C", "Java|C|Ruby")) ori_df # name like # 1: a R|python # 2: b python|C # 3: c Java|C|Ruby # 想得到这样的形式 # name like R python C Java Ruby # 1: a R|python 1 1 0 0 0 # 2: b python|C 0 1 1 0 0 # 3: c Java|C|Ruby 0 0 1 1 1
上面like这列数据,我们肯定是先要用strsplit拆分字符串,然后对每一个进行table统计(这只是一个例子,可以扩展到其他方面上的使用,比如一个人一段时间看过的电影类型汇总,这样就可能出现重复的,所以用table统计次数填入这个矩阵中)。这时出现了一个问题,就是对于每一个人,table只能统计出现过的软件,他们会的还都不一样,难以汇总在一起。这时就想到我们可以将其转化为factor,设定levels是所有的这些软件,再统计个数,没有出现过的就会为0,然后合并起来就好了。代码如下
(u <- strsplit(ori_df$like,"\\|") %>% unlist %>% unique) f <- function(x){ unlist(strsplit(x,"\\|")) %>% factor(levels=u) %>% table } ori_df[,(u):=transpose(lapply(ori_df$like, f))][]
插一个题外话(和factor无关),这样的数据还可以转化为如下形式来处理
# 想得到这样的形式 # name like 1 2 3 # 1: a R|python R python NA # 2: b python|C python C NA # 3: c Java|C|Ruby Java C Ruby df1 <- as.data.frame(tstrsplit(ori_df$like,"\\|")) colnames(df1) <- 1:3 cbind(ori_df,df1)
3.将定序变量转化为哑变量
思路如下:我们创建一个全是0的矩阵,再将应该改为1的索引位置赋值为1. 寻找索引位置的方法:将矩阵看成一个向量,接受一个索引而不是2个,然后将定序变量转化为数字1234加入计算,这个转化的过程最简单的就是转化为因子型再用unclass转化为数值型向量
class.ind <- function(cl) { n <- length(cl) cl <- as.factor(cl) x <- matrix( 0, n , length(levels(cl)) ) x[(1:n) + n*(unclass(cl)-1)] <- 1 dimnames(x) <- list(names(cl), levels(cl)) x } # 测试 x <- c("a","a","b","b","c","c") class.ind(x)
下面我们把这部分补充完整(虽然和factor也没什么关系)。我们需要在数据框中去除原来的这一列数据,再把新得到的数据去掉一列以防止多重共线性,最后将二者合并在一起,代码如下
library(data.table) # 配合data.table包使用 # 将数据框和那一列的字符串输入,即可得到新的数据框 # 结果返回哑变量中去除的列名,以及去除一个哑变量再合并之后的数据框,同时打印出去除了的哑变量名字 classdf <- function(dt, x){ cl <- class.ind(dt[[x]]) print(colnames(cl)[1]) cbind(dt[,-x,with=F], cl[,-1]) } df <- data.table(a=1:3,b=2:4,c=3:5) new <- classdf(df,"a") new # 改进函数,接受一个字符串向量,同时对多列进行相同处理 multiclassdf <- function(dt, xs){ l <- lapply(dt[, xs, with=F], class.ind) print(unlist(lapply(l, function(x) colnames(x)[1]))) Reduce(function(x,y) cbind(x,y[,-1]), l, dt[, -xs, with=F]) } multiclassdf(df, c("a","b"))
文末彩蛋
推荐rstudio脚本文件分块索引的技巧
-
在 .R 文件中,# part1--------- 单独成行,将代码按照层级分块,点击前面的三角符号,可以将这一部分代码折叠起来,同时可以在脚本区域下边栏上查看分块目录 part1 part2 等,快速定位所要寻找的内容
-
在 .rmd 文件中,# ## 是分级标题,也可以在下边栏查看目录。```{r} 这种代码块也会出现在下方目录之中,代码块也可以命名,方便快速查找 ```{r part1}
-
这些块都可以折叠成一行,再配合快捷键 alt + 上下,可以实现整个块的移动
往期回顾
公众号后台回复关键字即可学习
回复 爬虫 爬虫三大案例实战
Python
1小时破冰入门
回复 数据挖掘 R语言入门及数据挖掘
回复 人工智能 三个月入门人工智能
回复 数据分析师 数据分析师成长之路
回复 机器学习 机器学习的商业应用
回复 数据科学 数据科学实战
常用算法
常用数据挖掘算法
本文由R语言中文社区 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Python数据处理(二):处理 Excel 数据
- 大数据 -- 下一代数据处理技术
- Python数据抓取(1) —数据处理前的准备
- 大数据生态圈之流式数据处理框架选择
- 流式数据处理在百度数据工厂的应用与实践
- 5个大数据处理/数据分析/分布式工具
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
ASP.NET揭秘
Stephen Walther、汤涛 / 汤涛 / 中国电力出版社 / 2004-8-1 / 95.00元
本书是美国亚马逊网站同类书长期销售冠军,并受到微软ASP.NET小组项目经理Rob Howard的大力推荐,中文版由中科院专家汤涛老师翻译,经典、权威是本书最好的诠释。 本书共分10部分,31章,囊括了在.NET框架下架建ASP.NET应用程序的各个层面。每一章也都不是泛泛而谈理论,而是围绕实际样例代码来组织,让读者马上可以上手,并且加深理解。书中还包含了两个完整的、立即就可以用得......一起来看看 《ASP.NET揭秘》 这本书的介绍吧!