R因子的算术运算

Mic*_*ael 7 r r-faq

我有一个R数据帧,我试图从另一列中减去一列.我使用$运算符提取列,但列的类是'因子',R不会对因子执行算术运算.有这些特殊功能吗?

Ari*_*man 21

如果你真的想要使用因子的水平,你要么做了一些非常错误的事情,要么为了自己的利益而过于聪明.

如果您拥有的是包含存储在因子级别中的数字的因子,那么您希望首先使用as.numeric(as.character(...))以下代码将其强制转换为数字:

dat <- data.frame(f=as.character(runif(10)))
Run Code Online (Sandbox Code Playgroud)

您可以在此处查看访问因子索引和分配因子内容之间的区别:

> as.numeric(dat$f)
 [1]  9  7  2  1  4  6  5  3 10  8
> as.numeric(as.character(dat$f))
 [1] 0.6369432 0.4455214 0.1204000 0.0336245 0.2731787 0.4219241 0.2910194
 [8] 0.1868443 0.9443593 0.5784658
Run Code Online (Sandbox Code Playgroud)

计时与仅在水平上进行转换的替代方法表明,如果每个元素的级别不是唯一的,那么它会更快:

dat <- data.frame( f = sample(as.character(runif(10)),10^4,replace=TRUE) )
library(microbenchmark)
microbenchmark(
  as.numeric(as.character(dat$f)),
  as.numeric( levels(dat$f) )[dat$f] ,
  as.numeric( levels(dat$f)[dat$f] ),
  times=50
  )

                              expr     min      lq  median      uq     max
1  as.numeric(as.character(dat$f)) 7835865 7869228 7919699 7998399 9576694
2 as.numeric(levels(dat$f))[dat$f]  237814  242947  255778  270321  371263
3 as.numeric(levels(dat$f)[dat$f]) 7817045 7905156 7964610 8121583 9297819
Run Code Online (Sandbox Code Playgroud)

因此,如果length(levels(dat$f)) < length(dat$f),as.numeric(levels(dat$f))[dat$f]用于大幅度的速度增益.

如果length(levels(dat$f))大致相等length(dat$f),则没有速度增益:

dat <- data.frame( f = as.character(runif(10^4) ) )
library(microbenchmark)
microbenchmark(
  as.numeric(as.character(dat$f)),
  as.numeric( levels(dat$f) )[dat$f] ,
  as.numeric( levels(dat$f)[dat$f] ),
  times=50
  )

                              expr     min      lq  median      uq      max
1  as.numeric(as.character(dat$f)) 7986423 8036895 8101480 8202850 12522842
2 as.numeric(levels(dat$f))[dat$f] 7815335 7866661 7949640 8102764 15809456
3 as.numeric(levels(dat$f)[dat$f]) 7989845 8040316 8122012 8330312 10420161
Run Code Online (Sandbox Code Playgroud)

  • @Brandon:除非有人使用`relevel`或整数序列不连续.假设级别索引与级别内容相同似乎是一个危险的假设. (2认同)