2015-10-07 2 views
4

я только что заметил следующее:Почему фактор-векторы менее эффективны, чем целые или даже векторы символов?

set.seed(42) 
vec <- sample(c("a", "b", "c"), 1e4, replace=T) 
vec_fac <- factor(vec) 
vec_int <- as.integer(factor(vec)) 

library(microbenchmark) 
microbenchmark(vec=="b", vec_fac=="b", vec_int==2, vec_fac==2) 

Это дает к моему большому удивлению:

Unit: microseconds 
      expr  min  lq  mean median  uq  max neval 
    vec == "b" 2397.150 2406.5925 2499.5715 2470.637 2532.628 2881.588 100 
vec_fac == "b" 5706.932 5765.4340 6137.5441 6032.696 6401.567 8889.446 100 
    vec_int == 2 510.714 541.0935 623.8341 580.506 743.695 845.305 100 
    vec_fac == 2 5703.237 5772.6185 6339.6577 5975.015 6378.577 31502.869 100 

я бы подумал, что факторы были гораздо более эффективны, чем простой вектор символов, но это не так , (Конечно, vec_fac и vec_int занимают половину меньше памяти, чем vec.)

Почему факторы не так эффективны, как целые векторы?

ответ

4

Тестирование требует некоторой конверсии. Посмотрите на профилирование ниже. Обратите внимание, что (levels(vec_fac) == "b")[vec_fac] быстрее.

set.seed(42) 
vec <- sample(c("a", "b", "c"), 1e4, replace=T) 
vec_fac <- factor(vec) 
vec_int <- as.integer(factor(vec)) 

library(microbenchmark) 
microbenchmark(
    (levels(vec_fac) == "b")[vec_fac], 
    vec_int == 2, 
    vec == "b", 
    vec_fac == 2, 
    vec_fac == "b" 
) 
Unit: microseconds 
           expr  min  lq  mean median  uq  max neval cld 
(levels(vec_fac) == "b")[vec_fac] 62.861 69.7030 74.20981 71.8410 73.552 131.280 100 a  
         vec_int == 2 73.124 85.0970 89.96756 86.8070 87.877 125.721 100 b 
         vec == "b" 129.569 133.8450 138.57510 134.7005 135.129 170.621 100 c 
         vec_fac == 2 303.611 331.8340 348.90436 334.6135 337.820 482.783 100 d 
        vec_fac == "b" 347.656 376.7335 393.01326 379.2990 381.224 577.715 100  e 

Профилирование:

set.seed(42) 
vec <- sample(c("a", "b", "c"), 1e8, replace=T) 
vec_fac <- factor(vec) 
vec_int <- as.integer(vec_fac) 

Rprof() 
junk <- vec_int == 2 
Rprof(NULL) 
summaryRprof() 

Rprof() 
junk <- vec == "b" 
Rprof(NULL) 
summaryRprof() 

Rprof() 
junk <- vec_fac == "b" 
Rprof(NULL) 
summaryRprof() 

Rprof() 
junk <- vec_fac == 2 
Rprof(NULL) 
summaryRprof() 
+0

Я не уверен, как интерпретировать вывод профилирования, не могли бы вы уточнить, что вы видите? –

+0

Для векторных сравнений требуется только функция '=='. Для сравнения на основе факторов необходимы дополнительные функции, такие как 'Ops.factor'. Следовательно, они, скорее всего, потребуют больше времени. – Thierry

Смежные вопросы