2016-04-07 3 views
3

У меня есть dataframe (намного больше моих «реальных» данных):R соответствующий ID столбца номер строки

df = data.frame(id = c(1, 2, 2, 5, 6, 7), value = c("A", "B", "C", "D", "E", "F")) 

который я затем преобразовать в список:

list = split(df$value, df$id) 

Я теперь хочу эффективно получать значения в списке по их идентификатору. Очевидно, я мог бы использовать

list[["6"]] 

, чтобы получить «E». По-видимому, с увеличением идентификационных номеров требуется больше времени для доступа к значениям. Представьте себе гораздо больший список, доступ к каждому значению от 10001-20000 занимает больше времени, чем доступ к 1-10000.

Как получить доступ к значениям быстрее? Моя идея заключалась в том, что я сопоставляю идентификатор строки с идентификатором в списке, так что list[["6"]] == list[[6]], но как я могу это сделать? Есть ли лучшие варианты?

Редактировать: дополнительная информация в контексте. Я использую функцию, подобную этой:

test_function = function(a, b) { 
    a = unique(list[[a]]) 
    b = unique(list[[b]]) 
    return (length(intersect(a, b))) 
} 

Использование применять на dataframe который выглядит следующим образом:

 a  b 
1 36 38 
2 38 39 
3 39 36 
4 95 96 
5 96 95 
6 190 191 
7 191 192 
8 192 190 
9 193 194 
10 194 196 

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

Редактировать2: Спасибо за все ваши ответы. Я проверил все из предложенных подходов и выяснил, что для моей конкретной цели, ответ digEmAll был самым быстрым способом:

myEnv <- list2env(list) 
get("10000",envir=myEnv) 
+2

Чтобы получить„E“не вы' список [[»6 ']] 'или' list [[4]] '? –

+0

Да, спасибо, что заметили! – aseipel

+0

Я бы подумал о том, чтобы смотреть на 'lapply' и' sapply', поскольку они работают намного быстрее. Похоже, что это связано с поисковой оптимизацией. – giraffehere

ответ

3

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

df <- data.frame(id = 1:1000000) 
df$val <- c("A", "B", "C", "D", "E") 
mylist <- split(df$val, df$id) 

library(hash) 
myhash <- hash(mylist) 
myhash[["2"]] 
[1] "B" 

Бенчмаркинг:

microbenchmark::microbenchmark(
    myhash[["1000000"]], 
    mylist[["1000000"]] 
) 
Unit: microseconds 
       expr  min  lq  mean  median  uq  max neval 
    myhash[["1000000"]] 25.466 33.828 72.85514 103.5735 107.565 133.03 100 
mylist[["1000000"]] 10765.207 10957.911 11076.01143 11044.0010 11120.398 12145.30 100 

Один недостаток будет потеря совместимости, но для этого он должен хорошо работать

2

Благодарим вас за все ваши ответы. Я проверил все из предложенных подходов и выяснили, что для моей конкретной цели, digEmAll «s ответ был самый быстрый способ:

myEnv <- list2env(list) 
get("10000",envir=myEnv) 
Смежные вопросы