2015-05-06 3 views
2

У меня возникли проблемы с пониманием того, как data.frame строительные работы.Выполнение задания в конструкторе data.frame

Я видел this question, но я думал, что предварительное назначение столбцов в data.frame было медленным, если вы захотели заменить данные после этого (дублированная работа).

Затем я выполнил следующий тест и обнаружил, что передача данных в качестве аргументов в конструктор data.frame намного медленнее, чем просто создание data.frame, а затем назначение данных.

Что здесь происходит?

library(microbenchmark) 


# Prep -------------------# 

n = 1000 
s = seq(n) 

f = runif(n) 
g = as.factor(sample(1:100, size = n, replace = T)) 
h = runif(n) 
i = sample(LETTERS[1:26], size = n, replace = T) 


# Functions --------------# 

## Construct data.frame and then assign 
f_dollar = function(){ 
    d = data.frame(row.names = s, 
        check.rows = F, check.names = F, stringsAsFactors = F) 
    d$first = f 
    d$second = g 
    d$third = h 
    d$fourth = i 
} 


## Construct data.frame assigning named vectors 
f_named = function(){ 
    d = data.frame(first = f, second = g, third = h, fourth = i, 
        check.rows = F, check.names = F, stringsAsFactors = F) 
} 

## Construct data.frame assigning unnamed vectors 
f_unnamed = function(){ 
    d = data.frame(f, g, h, i, 
        check.rows = F, check.names = F, stringsAsFactors = F) 
} 


# Profile ----------------# 

microbenchmark(f_dollar(), f_named(), f_unnamed()) 

И результаты:

Unit: microseconds 
     expr  min  lq  mean median  uq  max neval 
    f_dollar() 65.808 79.691 92.5668 87.3850 100.6715 191.446 100 
    f_named() 205.962 221.761 245.2758 231.8325 251.2915 538.911 100 
f_unnamed() 269.416 283.689 339.8429 297.1045 332.8925 2800.185 100 
+1

Согласен, ваши результаты вначале не интуитивно понятны, но могут быть побочным продуктом использования таких небольших наборов данных. Если вы набросаете свой n до 100000, вы должны увидеть результаты, соответствующие вашим ожиданиям (по крайней мере, я). –

+1

Если вы посмотрите на код для 'data.frame', вы можете заметить, что в случае отсутствия данных (как в' f_dollar') он выходит очень рано. Мое предположение заключалось бы в том, что '$ <-' имеет меньше накладных расходов, чем взбалтывание остальной части кода в 'data.frame', по крайней мере, для масштаба данных в этом примере. – joran

ответ

1

Изменение n=100000 и запуск ваших microbenchmark() для 1000 испытаний, чтобы сглаживать любые изменения приводит к следующему:

> microbenchmark(f_dollar(), f_named(), f_unnamed(), times=1000) 
Unit: microseconds 
     expr  min  lq  mean  median  uq  max neval 
    f_dollar() 16559.490 17000.361 17444.4909 17282.3785 17587.723 24130.81 1000 
    f_named() 211.338 233.266 277.4680 254.2595 302.779 2028.94 1000 
f_unnamed() 260.325 288.783 391.2701 313.7420 366.693 44304.51 1000 

Это будет поддерживать ваше первоначальное впечатление, что создание объекта data.frame с включенными данными намного эффективнее, чем добавление его после факта, который воссоздает data.frame для каждой переменной добавьте, насколько я знаю.

+0

Какую версию R вы проверили? – MrFlick

+0

3.1.2, вы видите значительно разные результаты для разных версий R? –

+0

thx, имеет смысл, когда я действительно смотрю код data.frame – dudu

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