处理零';在R中进行日志转换时(受其他约束)
我有一种情况,我需要对数据进行日志转换以使用它,但我的矩阵中有零。除了0之外,我的矩阵也是从Dirichlet分布中提取的,这意味着矩阵有一个约束,即所有列式和必须加起来等于1。以下是数据:处理零';在R中进行日志转换时(受其他约束),r,transformation,logarithm,R,Transformation,Logarithm,我有一种情况,我需要对数据进行日志转换以使用它,但我的矩阵中有零。除了0之外,我的矩阵也是从Dirichlet分布中提取的,这意味着矩阵有一个约束,即所有列式和必须加起来等于1。以下是数据: > q[1:10, 1:5] V1 V2 V3 V4 V5 1 0.534410243 0.009358740 0.011295181 0.2141751740 0.0030129254 2 0.0
> q[1:10, 1:5]
V1 V2 V3 V4 V5
1 0.534410243 0.009358740 0.011295181 0.2141751740 0.0030129254
2 0.026653603 0.372426720 0.447847534 0.0179177507 0.4072904477
3 0.193317915 0.003605024 0.003186611 0.4832114736 0.0007095471
4 0.111881585 0.000000000 0.000000000 0.2296213741 0.0119233461
5 0.089696570 0.591163629 0.509774416 0.0032542030 0.5535847030
6 0.007543558 0.000000000 0.000000000 0.0364907757 0.0013148362
7 0.004862942 0.000000000 0.002123909 0.0146682272 0.0004053690
8 0.009276195 0.011710457 0.014367894 0.0000000000 0.0000000000
9 0.006903171 0.004314528 0.011404455 0.0000000000 0.0126889937
10 0.015454219 0.007420903 0.000000000 0.0006610215 0.0090698319
请注意,q的所有列相加为一
> colSums(q)[1:5]
V1 V2 V3 V4 V5
1 1 1 1 1
我需要像这样取log(q):
正如您所看到的,有大量的-Inf值扰乱了我的计算。我曾想过用非常小的数字来代替零,但是在列之间的和不再是1。我如何编写代码来构造q的替代矩阵,1)没有零值,因此绕过了日志(0)问题,2)仍然有添加到1的列,并且不改变跨行数据的基本分布
非常感谢
编辑:为了提供更广泛的上下文:我需要进行日志转换,因为我将输出输入到计算日志似然函数中。在我的应用程序中,我正在重新参数化Dirichlet分布的对数似然函数,因此我没有从包中调用通用的对数似然函数
以下是我的整体功能:
llikelihood = function(alpha0, beta, q, d, n) {
llike = n*(lgamma(alpha0) - sum_a(alpha0, beta, d) + sum_b (alpha0, beta, q, d, n))
return(llike)
}
sum_a = function(alpha0, beta, d) {
sum_a = 0
for (i in 1:d) {
sum_a = sum_a + lgamma(alpha0*beta[i])
}
return(sum_a)
}
# returns the output to summation from 1 to k of (alpha0*beta[i] - 1)*log(x_i)
sum_b = function(alpha0, beta, q, d, n) {
# replace zero values
sum_b = 0
# find the log q
logq = log(q)
qlog = apply(logq, 1, sum)
# for each column, sum up the draws
for (i in 1:d) {
sum_b = sum_b + (alpha0*beta[i] - 1)*1/n*qlog[i]
}
# apply(log(q), 2, sum)
return(sum_b)
}
这里,sum_b
是我计算log(q)的地方,如上所述。如您所见,我的问题是我需要去掉零,将数据规范化为1,然后记录它。如何编写高效的代码?我猜这会像拉普拉斯平滑,但我对它了解不多,而且我对R编程还不熟悉。非常感谢您的评论 1)您可以尝试其他不返回带零的-Inf的转换,例如平方根或立方根
2) 通过将所有元素除以它们的列和来规范化1)的结果
set.seed(123)
X <- t(rdirichlet(4, alpha=c(1,0,2,1)))
X
[,1] [,2] [,3] [,4]
[1,] 0.03562445 0.3384606 0.5700819 0.01357789
[2,] 0.00000000 0.0000000 0.0000000 0.00000000
[3,] 0.64748450 0.2927702 0.3297736 0.88378152
[4,] 0.31689105 0.3687692 0.1001445 0.10264059
colSums(X)
# [1] 1 1 1 1
set.seed(123)
x1)进行另一个变换,例如平方根或立方根。2) 重新缩放?一旦数据被日志转换,它在列中的总和将不再为1,无论-Inf问题如何。这可能是一个“X-Y”问题;为这个问题提供更广泛的上下文可能会得到更多有用的答案。您好,由于我的代码的上下文(我在上面添加了更多细节),进行另一个转换是很困难的。我不需要在log变换后将列和设为1,只需要在log变换前将其设为1,以确保Q仍然表示从Dirichlet分布提取的数据。谢谢
set.seed(123)
X <- t(rdirichlet(4, alpha=c(1,0,2,1)))
X
[,1] [,2] [,3] [,4]
[1,] 0.03562445 0.3384606 0.5700819 0.01357789
[2,] 0.00000000 0.0000000 0.0000000 0.00000000
[3,] 0.64748450 0.2927702 0.3297736 0.88378152
[4,] 0.31689105 0.3687692 0.1001445 0.10264059
colSums(X)
# [1] 1 1 1 1
X2 <- sqrt(X); X2
[,1] [,2] [,3] [,4]
[1,] 0.1887444 0.5817737 0.7550377 0.1165242
[2,] 0.0000000 0.0000000 0.0000000 0.0000000
[3,] 0.8046642 0.5410824 0.5742592 0.9400966
[4,] 0.5629308 0.6072637 0.3164561 0.3203757
X3 <- sweep(X2, 2, colSums(X2), FUN="/"); X3
[,1] [,2] [,3] [,4]
[1,] 0.1212746 0.3362621 0.4587794 0.08462201
[2,] 0.0000000 0.0000000 0.0000000 0.00000000
[3,] 0.5170236 0.3127428 0.3489340 0.68271531
[4,] 0.3617018 0.3509952 0.1922865 0.23266269
> colSums(X3)
[1] 1 1 1 1