Эффективное вычисление линейной комбинации столбцов data.table

У меня есть nc столбцы в data.table и nc скалярах в векторе. Я хочу взять линейную комбинацию столбцов, но я заранее не знаю, какие столбцы я буду использовать. Каков наиболее эффективный способ сделать это?

настроить

 require(data.table) set.seed(1) n <- 1e5 nc <- 5 cf <- setNames(rnorm(nc),LETTERS[1:nc]) DT <- setnames(data.table(replicate(nc,rnorm(n))),LETTERS[1:nc]) 

способы сделать это

Предположим, я хочу использовать первые четыре столбца. Я могу писать вручную:

 DT[,list(cf['A']*A+cf['B']*B+cf['C']*C+cf['D']*D)] 

Я могу думать о двух автоматических способах (которые работают, не зная, что AE следует использовать):

 mycols <- LETTERS[1:4] # the first four columns DT[,list(as.matrix(.SD)%*%cf[mycols]),.SDcols=mycols] DT[,list(Reduce(`+`,Map(`*`,cf[mycols],.SD))),.SDcols=mycols] 

бенчмаркинг

Я ожидаю, что as.matrix сделает второй вариант медленным, и на самом деле не имеет интуиции для скорости MapReduce комбинации.

 require(rbenchmark) options(datatable.verbose=FALSE) # in case you have it turned on benchmark( manual=DT[,list(cf['A']*A+cf['B']*B+cf['C']*C+cf['D']*D)], coerce=DT[,list(as.matrix(.SD)%*%cf[mycols]),.SDcols=mycols], maprdc=DT[,list(Reduce(`+`,Map(`*`,cf[mycols],.SD))),.SDcols=mycols] )[,1:6] test replications elapsed relative user.self sys.self 2 coerce 100 2.47 1.342 1.95 0.51 1 manual 100 1.84 1.000 1.53 0.31 3 maprdc 100 2.40 1.304 1.62 0.75 

Я получаю от 5% до 40% -ного замедления относительно ручного подхода, когда я повторяю benchmark вызов.

мое заявление

Размеры здесь – n и length(mycols) – близки к тому, с чем я работаю, но я буду многократно выполнять эти вычисления, изменяя вектор коэффициентов, cf

Для меня это почти в 2 раза быстрее, чем ваша ручная версия:

 Reduce("+", lapply(names(DT), function(x) DT[[x]] * cf[x])) benchmark(manual = DT[, list(cf['A']*A+cf['B']*B+cf['C']*C+cf['D']*D)], reduce = Reduce('+', lapply(names(DT), function(x) DT[[x]] * cf[x]))) # test replications elapsed relative user.self sys.self user.child sys.child #1 manual 100 1.43 1.744 1.08 0.36 NA NA #2 reduce 100 0.82 1.000 0.58 0.24 NA NA 

И, чтобы mycols только mycols , замените names(DT) mycols в lapply .

Добавьте этот вариант в свой тестовый вызов:

 ops = as.matrix(DT) %*% cf 

На моем устройстве он был на 30% быстрее, чем матричное умножение, которое вы пытались.

  • более быстрый способ создания переменной, которая агрегирует столбец по id
  • Почему XCHG reg, reg 3 инструкции по микрооперации на современных архитектурах Intel?
  • почему GCC __builtin_prefetch не улучшает производительность?
  • Переходы CSS3: «Переход: все» медленнее, чем «переход: x»?
  • Почему автореферат особенно опасен / дорого для приложений iPhone?
  • Какие счетчики perfmon полезны для выявления узких мест ASP.NET?
  • Почему JSF вызывает геттеры несколько раз
  • MySQL: самый быстрый способ подсчета количества строк
  • Снижение производительности String.intern ()
  • Знать какие-либо инструменты анализа журналов сбора мусора Java?
  • Самый эффективный список методов data.frame?
  • Interesting Posts

    Когда предпочтительнее использовать volatile boolean в Java, а не AtomicBoolean?

    Outlook 2013 не показывает электронные письма старше, чем aprox. 6 месяцев в любых папках

    Почему не может быть -z быть последним вариантом командной строки, который будет использоваться с tar?

    tkinter: использование полос прокрутки на canvasе

    Как автоматически обнаружить порт Arduino COM?

    Создание симметричной матрицы в R

    Два компьютера с объединенными ресурсами процессора и памяти?

    Не удается разрешить символ HttpGet, HttpClient, HttpResponce в Android Studio

    Как настроить панель инструментов gvim?

    Выпадающее меню выпадающего списка Bootstrap отсутствует

    Может ли массив быть JSON-текстом верхнего уровня?

    Как написать новый символ строки в файл в Java

    R усиливает местный охват

    Разница между указателем и ссылкой как параметр streamа

    Github для Mac устанавливает веб-сервер, «github conduit». Это риск для безопасности?

    Давайте будем гением компьютера.