Арифметические операции на R факторах

У меня есть R-кадр данных, и я пытаюсь вычесть один столбец из другого. Я извлекаю столбцы, используя $ оператор, но класс столбцов 'factor' и R не будет выполнять арифметические операции над факторами. Существуют ли специальные функции для этого?

4 ответа

Решение

Если вы действительно хотите использовать уровни фактора, вы либо делаете что-то очень неправильное, либо слишком умное для своего же блага.

Если то, что у вас есть, является фактором, содержащим числа, хранящиеся на уровнях фактора, то сначала вы хотите привести его к числовому, используя as.numeric(as.character(...)):

dat <- data.frame(f=as.character(runif(10)))

Вы можете увидеть разницу между доступом к индексам факторов и назначением содержимого факторов здесь:

> 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

Время по сравнению с альтернативным подходом, который только делает преобразование на уровнях, показывает, что это быстрее, если уровни не уникальны для каждого элемента:

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

Следовательно, если 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

Вы можете определить свои собственные операторы для этого, см. ? Arith, Без групповых обобщений вы можете определить свои собственные бинарные операторы%operator%:

%-% <- function (factor1, factor2){
  # put in the code here to calculate difference 
  # of two factors (e.g. facor1 level cat - factor2 level mouse = ?)
}

Сначала вы должны проверить, как вы извлекаете данные. Если это действительно числовые столбцы, R должен это распознать (Excel иногда ошибается). В любом случае, это может быть вызвано фактором, потому что в столбцах есть другие нежелательные. Ответы, которые вы получили до сих пор, не упоминали, что as.numeric() возвращает только номера уровней. Это означает, что вы не будете выполнять операцию с фактическими числами, которые были преобразованы в факторы, а скорее с уровнями, связанными с каждым фактором.

Вам нужно будет преобразовать коэффициенты в числовые массивы.

a <- factor(c(5,6,5))
b <- factor(c(3,2,1))
df <- data.frame(a, b)

# WRONG: Factors can't be subtracted.
df$a - df$b

# CORRECT: Get the levels and substract
as.numeric(levels(df$a)[df$a]) - as.numeric(levels(df$b)[df$b])
Другие вопросы по тегам