Как быстро выполнить поиск внутри большой таблицы данных (57M obs)? - PullRequest
1 голос
/ 15 октября 2019

Как выполнить быстрый поиск в таблице данных с использованием sqldf?

Мне нужна функция, которая возвращает значение столбца data.table на основе двух других значений столбца:

require(data.table)

dt <- data.table(
    "base" = c("of", "of", "of", "lead and background vocals", "save thou me from", "silent in the face"),
    "prediction" = c("the", "set", "course", "from", "the", "of"),
    "count" = c(258586, 246646, 137533, 4, 4, 4)
)

> dt
#                         base prediction  count
#1:                         of        the 258586
#2:                         of        set 246646
#3:                         of     course 137533
#4: lead and background vocals       from      4
#5:          save thou me from        the      4
#6:         silent in the face         of      4

# the function needs to return the "prediction" value based on the max "count" value for the input "base" value.
# giving the input "of" to function:
> prediction("of")
# the desired output is:
> "the"
# or:
> prediction("save thou me from")
> "the"

Предоставленное здесь решение Как извлечь значения из таблицы данных на основе нескольких условий? работает с небольшими наборами данных, но не с очень большими таблицами данных (57M obs):

f1 <- function(val) dt[base == val, prediction[which.max(count)]]

Я читал, что индексирование data.table и поиск с использованием sqldf функций могут ускорить его, но пока не знаю, как это сделать.

Спасибо за продвижение.

Ответы [ 2 ]

4 голосов
/ 15 октября 2019

Вы можете рассмотреть возможность использования только data.table следующим образом. Я думаю, что это может значительно улучшить скорость.

dt <- data.table(
"base" = c("of", "of", "of", "lead and background vocals", "save thou me from", 
"silent in the face"),
"prediction" = c("the", "set", "course", "from", "the", "of"),
"count" = c(258586, 246646, 137533, 4, 4, 4)
)

# set the key on both base and count.
# This rearranges the data such that the max value of count for each group in base 
# corresponds to the last row.
setDT(dt, key = c("base", "count"))

# for a given group in base, we consider only the last value of prediction as it is 
# on the same row with the max value of count. 
prediction <- function(x) {
  dt[.(x), prediction[.N] ]
}

prediction("of")
#"the"
prediction("save thou me from")
#"the"
2 голосов
/ 15 октября 2019

Использование sqldf было бы так. Добавьте dbname = tempfile() аргумент, если вы не можете поместить его в память.

library(sqldf)

val <- "of"
fn$sqldf("select max(count) count, prediction from dt where base = '$val'")
##   count prediction
##1 258586        the

Альтернативно, чтобы настроить базу данных напрямую с использованием RSQLite и создать индекс:

library(gsubfn)
library(RSQLite)

con <- dbConnect(SQLite(), "dt.db")
dbWriteTable(con, "dt", dt)
dbExecute(con, "create index idx on dt(base)")

val <- "of"
fn$dbGetQuery(con, "select max(count) count, prediction from dt where base = '$val'")
##    count prediction
## 1 258586        the

dbDisconnect(con)

Примечание

Запустите это сначала:

library(data.table)

dt <- data.table(
    "base" = c("of", "of", "of", "lead and background vocals", 
     "save thou me from", "silent in the face"),
    "prediction" = c("the", "set", "course", "from", "the", "of"),
    "count" = c(258586, 246646, 137533, 4, 4, 4)
)
...