Как использовать функцию get () векторизованную при создании новых столбцов в data.tables? - PullRequest
1 голос
/ 07 апреля 2020

Я пытаюсь приспособить распределение к моим данным из таблицы data.table и создать новую таблицу data.table, которая содержит дату, предполагаемые параметры и подразумеваемый 75-й процентиль. Однако, когда я пытаюсь вычислить 75-й процентиль, я замечаю, что мой код не использует столбец sd. Пожалуйста, рассмотрите следующий пример кода:

library(fitdistrplus)

distribution <- 'norm'
dt <- data.table(Date = c('2012', '2013', '2014'),
                 mean = 1:3,
                 sd = c(0.1, 0.2, 0.3))

x <- rnorm(100, 1, 0.2)
# I'm trying to write code which not only allows distributions with mean and sd parameters.
paramNames <- names(fitdist(x, distr = distribution)$estimate)
qFunctionName <- eval(get(paste0('q',distribution)))
qName <- paste0('percentile', '75')

print(dt[, eval(qName) := qFunctionName(p = 0.75, get(paramNames))])

#    Date mean  sd percentile75
# 1: 2012    1 0.1      1.67449
# 2: 2013    2 0.2      2.67449
# 3: 2014    3 0.3      3.67449

dt[1, percentile75] == qnorm(0.75, mean = 1, sd = 0.1)
# > FALSE
dt[1, percentile75] == qnorm(0.75, mean = 1, sd = 1)
# > TRUE

Очевидно, get () не может также учитывать столбец sd. Как изменить код так, чтобы он занимал все столбцы с именами столбцов, сохраненными в объекте paramNames?

1 Ответ

4 голосов
/ 08 апреля 2020
library(fitdistrplus)

distribution <- 'norm'
dt <- data.table(Date = c('2012', '2013', '2014'),
    mean = 1:3,
    sd = c(0.1, 0.2, 0.3))

set.seed(0L)
x <- rnorm(100, 1, 0.2)
paramNames <- names(fitdist(x, distr = distribution)$estimate)
qFunctionName <- match.fun(paste0('q',distribution))
qName <- paste0('percentile', '75')

dt[, (qName) := do.call(qFunctionName, c(list(p=0.75), mget(paramNames)))][]
all.equal(dt[1, percentile75], qnorm(0.75, mean = 1, sd = 0.1))

В двух словах, get возвращает первое, только когда вектор передан в x, поэтому вам нужно mget (попробуйте get(c("x", "y")), где y не определено).

А также вам нужно do.call для создания и выполнения вызова функции.

А также не используйте == для проверки на двойной из-за проблем со стабильностью чисел c. На это есть много и много R вопросов.

...