在 data.tables 中创建新列时如何使用向量化的 get() 函数?
How to use get() function vectorized when creating new columns in data.tables?
我正在尝试从 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
对象中的列名的列?
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
只有 returns 第一个向量传递到 x
时,因此你需要 mget
(尝试 get(c("x", "y"))
其中y
未定义)。
并且您还需要 do.call
来构造和执行函数调用。
并且由于数值稳定性问题,也不要使用 ==
来测试 double。关于这个有很多 R 问题。
我正在尝试从 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
对象中的列名的列?
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
只有 returns 第一个向量传递到 x
时,因此你需要 mget
(尝试 get(c("x", "y"))
其中y
未定义)。
并且您还需要 do.call
来构造和执行函数调用。
并且由于数值稳定性问题,也不要使用 ==
来测试 double。关于这个有很多 R 问题。