R中的因素:多一个烦恼?

R中的基本数据types之一是因素。 在我的经验中,因素基本上是一种痛苦,我从不使用它们。 我总是转换成字符。 我觉得很奇怪,我错过了一些东西。

是否有一些重要的使用因子作为因子数据types变得必要的分组variables的函数示例? 我应该使用因素有什么具体情况?

你应该使用因素。 是的,他们可能是一个痛苦,但我的理论是,为什么他们是痛苦的90%是因为在read.tableread.csv ,参数stringsAsFactors = TRUE默认(和大多数用户错过这个微妙的)。 我认为它们是有用的,因为像lme4这样的模型拟合包使用因子和有序因子来区别地拟合模型,并确定使用的对比types。 而graphics包也使用它们来分组。 ggplot和大多数模型拟合函数ggplot字符向量的因子,所以结果是一样的。 然而,你最终在你的代码中的警告:

 lm(Petal.Length ~ -1 + Species, data=iris) # Call: # lm(formula = Petal.Length ~ -1 + Species, data = iris) # Coefficients: # Speciessetosa Speciesversicolor Speciesvirginica # 1.462 4.260 5.552 iris.alt <- iris iris.alt$Species <- as.character(iris.alt$Species) lm(Petal.Length ~ -1 + Species, data=iris.alt) # Call: # lm(formula = Petal.Length ~ -1 + Species, data = iris.alt) # Coefficients: # Speciessetosa Speciesversicolor Speciesvirginica # 1.462 4.260 5.552 

警告消息:在model.matrix.default(mt, mf, contrasts)

variablesSpecies转换为一个factor

一个棘手的事情是整个drop=TRUE位。 在向量中,这很好地消除了不在数据中的因素的级别。 例如:

 s <- iris$Species s[s == 'setosa', drop=TRUE] # [1] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa # [11] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa # [21] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa # [31] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa # [41] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa # Levels: setosa s[s == 'setosa', drop=FALSE] # [1] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa # [11] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa # [21] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa # [31] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa # [41] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa # Levels: setosa versicolor virginica 

但是 ,对于data.frame[.data.frame()的行为是不同的:请参阅此电子邮件或?"[.data.frame" 。 在data.frame上使用drop=TRUE不会像你想像的那样工作:

 x <- subset(iris, Species == 'setosa', drop=TRUE) # susbetting with [ behaves the same way x$Species # [1] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa # [11] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa # [21] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa # [31] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa # [41] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa # Levels: setosa versicolor virginica 

幸运的是,您可以使用小滴droplevels()轻松降低因子,以降低单个因子或数据data.frame每个因子的未使用因子水平(自R 2.12开始):

 x <- subset(iris, Species == 'setosa') levels(x$Species) # [1] "setosa" "versicolor" "virginica" x <- droplevels(x) levels(x$Species) # [1] "setosa" 

这是如何保持你从ggplot传说中select出来的水平。

在内部, factor s是具有属性级别字符向量的整数(参见attributes(iris$Species)class(attributes(iris$Species)$levels) ),这是干净的。 如果您必须更改级别名称(而且您正在使用string),则操作效率将会低很多 。 而且我更改了关卡的名字,尤其是对于ggplot传说。 如果你用angular色向量来伪造因素,那么就有可能只改变一个元素,并且意外地创build一个单独的新的级别。

有序的因素是可怕的,如果我碰巧喜欢桔子,讨厌苹果,但不介意葡萄我不需要pipe理一些奇怪的指数说:

 d <- data.frame(x = rnorm(20), f = sample(c("apples", "oranges", "grapes"), 20, replace = TRUE, prob = c(0.5, 0.25, 0.25))) d$f <- ordered(d$f, c("apples", "grapes", "oranges")) d[d$f >= "grapes", ] 

一个factor最类似于其他语言的枚举types。 其适当的用途是只能采取规定的一组值的variables。 在这些情况下,任何特定的数据集都不可能存在所有可能的值,而“空”的水平则准确地反映了这一点。

考虑一些例子。 对于全美国收集的一些数据,应该将州作为一个因素logging下来。 在这种情况下,没有从特定国家收集病例的事实是相关的。 可能有来自该州的数据,但是发生了(无论出于何种原因,这可能是感兴趣的原因)。 如果收集家乡,这不是一个因素。 没有预先说明的一组可能的家乡。 如果数据是从三个城镇而不是从全国收集的,那么这个城镇将是一个因素:一开始就有三个select,如果在三个城镇之一没有发现相关的案例/数据,那么这个数据是相关的。

factor s的其他方面,例如提供一种给一组string赋予任意sorting顺序的方法,是factor s的有用的次要特征,但不是它们存在的原因。

当进行统计分析和实际探索数据时,因素是非常棒的。 然而,在阅读,清理,故障排除,合并和一般操作数据之前,因素是一个总的痛苦。 最近,像过去几年一样,许多function已经改善,以更好地处理这些因素。 比如,rbind和他们很好地玩。 我仍然觉得在一个子集函数之后留下空的层次总是令人讨厌。

 #drop a whole bunch of unused levels from a whole bunch of columns that are factors using gdata require(gdata) drop.levels(dataframe) 

我知道,重新编码一个因素的水平和调整标签是很简单的,而且还有很好的方法来重新排列这个水平。 我的大脑根本不记得它们,每次使用它时都必须重新学习它。 重新编码应该比现在简单得多。

R的string函数非常容易和合乎逻辑地使用。 所以在操作时我通常比字符更喜欢字符。

多么讽刺的标题!

我相信很多评估函数允许你使用因子来简单地定义虚拟variables……但是我并没有使用它们。

当我有非常大的字符向量,并且很less有独特的观察值时,我使用它们 这可以减less内存消耗,特别是如果字符向量中的string更长的话。

PS – 我在开玩笑的标题。 我看到你的推特。 😉

因素是一个优秀的“独特案例”徽章引擎。 我已经重复了很多次,偶尔也会有一些皱纹,但是它们非常强大。

 library(dplyr) d <- tibble(x = sample(letters[1:10], 20, replace = TRUE)) ## normalize this table into an indexed value across two tables id <- tibble(x_u = sort(unique(d$x))) %>% mutate(x_i = row_number()) di <- tibble(x_i = as.integer(factor(d$x))) ## reconstruct d$x when needed d2 <- inner_join(di, id) %>% transmute(x = x_u) identical(d, d2) ## [1] TRUE 

如果有更好的方法来完成这个任务,我很乐意看到它,我没有看到这个讨论factor能力。

取决于 (和总计 )依赖于因素。 这些function的信息与努力比例非常高。

例如,在一行代码中(以下称为tapply ),您可以通过剪切和颜色获得钻石的平均价格:

 > data(diamonds, package="ggplot2") > head(dm) Carat Cut Clarity Price Color 1 0.23 Ideal SI2 326 E 2 0.21 Premium SI1 326 E 3 0.23 Good VS1 327 E > tx = with(diamonds, tapply(X=Price, INDEX=list(Cut=Cut, Color=Color), FUN=mean)) > a = sort(1:diamonds(tx)[2], decreasing=T) # reverse columns for readability > tx[,a] Color Cut JIHGFED Fair 4976 4685 5136 4239 3827 3682 4291 Good 4574 5079 4276 4123 3496 3424 3405 Very Good 5104 5256 4535 3873 3779 3215 3470 Premium 6295 5946 5217 4501 4325 3539 3631 Ideal 4918 4452 3889 3721 3375 2598 2629