2015-05-28 2 views
7

Предположим, что по какой-то причине I необходимо.Цитирование по строкам в информационном кадре

Я создаю простой data.frame

df <- data.frame(id = sample(1e6, 1e7, replace = TRUE)) 

кажется, что f2 гораздо медленнее, чем f1, в то время как я ожидал, что они эквивалентны.

f1 <- function(v){ 
     for (obs in 1:(1e6)){ 
      a <- v[obs] 
     } 
     a 
    } 
system.time(f1(df$id)) 

f2 <- function(){ 
     for (obs in 1:(1e6)){ 
      a <- df$id[obs] 
     } 
    a 
    } 
system.time(f2()) 

Вы знаете, почему? Используют ли они точно такой же объем памяти?

+3

С первой функции вы используете '$' один раз, во второй функции вы используете его 1e6 раз. '$' не самая быстрая функция подмножества. – Roland

+0

Меня удивляет то, что 'f1' в два раза быстрее, чем' f3 <- function (v) для (a в v) {NULL}; system.time (f3 (ДФ $ ID)) '. О, я вижу: '1e6' - это не полная длина вектора. 'system.time (f3 (df $ id [1: 1e6]))' быстро. – Frank

ответ

6

Если вы вместо того, чтобы писать свои тайминги, как это и признают, что df$x действительно вызов функции (до `$`(df,x)) тайна исчезает:

system.time(for(i in 1:1e6) df$x) 
# user system elapsed 
# 8.52 0.00 8.53 
system.time(for(i in 1) df$x) 
# user system elapsed 
#  0  0  0 
2

В f1 вы обходите рамку данных полностью, просто передавая вектор вашей функции. Таким образом, ваш код по существу «у меня есть вектор! Это первый элемент, это второй элемент. Это третий ...»

В отличие от этого, в f2 вы даете ему целый фрейм данных, а затем каждый элемент каждого столбца. Таким образом, ваш код: «У меня есть фрейм данных, это первый элемент столбца« Идентификатор ». Это второй элемент столбца« Идентификатор ». Это третий ...»

Это намного быстрее, если вы извлечете простая структура данных (вектор) один раз, а затем может работать только с этим, а не многократно извлекать простую структуру из более крупного объекта.

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