如何在 r 中的用户定义函数上使用 apply() - 错误地说它不是函数



我写了一个函数,它使用花的宽度和长度来计算二元正态分布的密度。我想将该函数应用于数据帧,以计算每行的密度。我正试图使用apply((函数来实现这一点,但它给了我一个错误,说我的函数不是函数。当我将函数用于单行时,它确实有效,所以我不认为这是函数本身的问题。我试着研究一下,但找不到太多关于如何在apply((中实现用户定义函数的信息。这是我的代码和一些示例数据。

density_fn<- function(x, y, mu_x, mu_y, sigma){
mean_vec<- matrix(c((x - mu_x), (y - mu_y)))
sigma_det<- det(sigma)
sigma_inv<- solve(sigma)
frac<- 1/(2*pi*sqrt(sigma_det))
exponent<- exp(-0.5%*%t(mean_vec)%*%sigma_inv%*%mean_vec)
den_fn<- frac*exponent
return(den_fn)
}
flower<- data.frame(
Width = c(20, 32, 29),
Length = c( 51, 66, 48)
)
flower_w_mean<- 27
flower_l_mean<- 55
cov_matrix<- matrix(c(39, 0, 0, 93), nrow=2, ncol=2) 
apply(flower, 1, FUN = density_fn(flower$Width, flower$Length, 
flower_w_mean, flower_l_mean, cov_matrix))

最初,我得到了这个错误:

-0.5%*%t(mean_vec(%*%sigma_inv中的错误:不一致的参数

我认为这是我的协方差矩阵的问题,所以我去掉了函数的第一行以外的所有内容,并返回mean_vec,这时我得到了这个错误:

match.fun(fun(中的错误:c("'density_fn(flower$Width,flower$Length,flower_w_mean,flower_l_mean,'不是函数、字符或符号","cov_matrix('不是函数或符号"(

有人知道如何将此函数正确应用于数据帧吗?

首先,让我解释一下您收到的两条错误消息。

第一个错误

-0.5%*%t(mean_vec(%*%sigma_inv中的错误:不一致的参数

此错误消息显示错误的原因是不符合规则的参数相乘。矩阵乘法A %*% B的规则是,如果是矩阵,A的列数必须等于B的行数,如果是向量,则A的长度必须等于。

density_fn中,定义mean_vec<- matrix(c((x - mu_x), (y - mu_y)))使mean_vec成为一个列恰好1且行数等于xy组合的总长度的矩阵。因此,如果sigma_inv>1,矩阵乘法CCD_ 12不符合规则。例如:

x <- 1:2  # length of 2
y <- 1:3 # length of 3 
sigma <- matrix(1:4, nrow = 2)
sigma_inv <- solve(sigma)
mean_vec <- matrix(c(x - mean(x), y - mean(y))) 
mean_vec # 1 row 5 columns
#     [,1]
#[1,] -0.5
#[2,]  0.5
#[3,] -1.0
#[4,]  0.0
#[5,]  1.0
t(mean_vec) %*% sigma_inv
# Error in t(mean_vec) %*% sigma_inv : non-conformable arguments

如果CCD_ 13和CCD_。这就是为什么当您将此函数用于单行时,它确实有效。例如:

x <- 2  # length of 1
y <- 3 # length of 1 
sigma <- matrix(1:4, nrow = 2)
mean_vec <- matrix(c(x - mean(x), y - mean(y))) 
sigma_inv <- solve(sigma)
t(mean_vec) %*% sigma_inv
#     [,1] [,2]
# [1,]    0    0

使函数在xy的任何长度上正常工作的另一种方法是如下设置mean_vec <- matrix()中的行数和列数:

mean_vec <- matrix(c((x - mu_x), (y - mu_y)), 
ncol = nrow(sigma), 
nrow = ncol(sigma))

然后将矩阵乘法CCD_ 18改变为标量乘法-0.5 * mean_vec

因此,函数变为:

density_fn <- function(x, y, mu_x, mu_y, sigma) {
mean_vec <- matrix(c((x - mu_x), (y - mu_y)), 
ncol = nrow(sigma), 
nrow = ncol(sigma))
sigma_det <- det(sigma)
sigma_inv <- solve(sigma)
frac <- 1 / (2 * pi * sqrt(sigma_det))
exponent <- exp(-0.5 * t(mean_vec) %*% sigma_inv %*% mean_vec)
den_fn <- frac * exponent
return(den_fn)
}

第二个错误

match.fun(fun(:c('density_fn(花$Width,花$Length,flower_w_mean,flower_l_mean,'不是函数、字符或符号"'cov_matrix('不是函数、字符或符号"(

此错误消息显示未正确指定applyFUN的值。根据apply的文档,分配给FUN的值应为

通常是一个函数或符号(例如,后引号名称(或者指定要从中搜索的函数的字符串应用的调用环境

这意味着您应该只向FUN提及函数名。函数的附加参数(第二个参数、第三个参数…(应在FUN之后提及,而不是在FUN中提及。请查看?apply了解详细信息。

然而,仅此步骤并不能解决问题,因为apply适用于单变量输入。因为您的输入是多变量的,所以mapply更适合。其他选项包括Map和使用for等的环路。

如何使用mapply应用函数

最好用一个简单的例子来解释。请查看?mapply了解详细信息。假设您有xy,并且您想要得到z = 2x + 3y。您希望将函数矢量化为xy

x <- c(3,4,5)
y <- c(10,20, 30)
myfun <- function(x,y) 2*x + 3*y
z <- mapply(myfun, x, y)
z
#[1]  36  68 100

如果在myfun中有xy以外的参数,则应将它们分配给MoreArgs。以下是使用density_fn的示例。

mapply(density_fn, x = flower$Width, y = flower$Length, MoreArgs = list(
mu_x = flower_w_mean, 
mu_y = flower_l_mean, 
sigma = cov_matrix))
#         [,1]        [,2]        [,3]
# [1,] 0.001293784 0.001000747 0.001929141
# [2,] 0.001293784 0.001000747 0.001929141
# [3,] 0.001293784 0.001000747 0.001929141
# [4,] 0.001293784 0.001000747 0.001929141

这些步骤不会产生错误。然而,由于我对这个主题的了解有限,我不能保证这些步骤能像你想要的那样正确地表示二元正态分布的密度函数。

最新更新