[R] Latin Hypercube with condition sum = 1
Rob Carnell
carnellr at battelle.org
Tue Nov 25 15:16:35 CET 2008
Rainer M Krug <r.m.krug <at> gmail.com> writes:
>
> Hi
>
> I want to du a sensitivity analysis using Latin Hypercubes. But my
> parameters have to fulfill two conditions:
>
> 1) ranging from 0 to 1
> 2) have to sum up to 1
>
> So far I am using the lhs package and am doing the following:
>
> library(lhs)
> ws <- improvedLHS(1000, 7)
> wsSums <- rowSums(ws)
> wss <- ws / wsSums
>
> but I think I can't do that, as after the normalization
>
> > min(wss)
> [1] 0.0001113015
> > max(wss)
> [1] 0.5095729
>
> Therefore my question: how can I create a Latin Hypercube whicgh
> fulfills the conditions 1) and 2)?
>
> Thanks a lot
>
> Rainer
>
Rainer,
Your original solution meets your two conditions. The problem for you (I
think) is that you'd like the result to have values near zero and near one.
I have an imperfect solution to your problem using a Dirichlet distribution.
The Dirichlet seems to keep the range of the values larger once they are
normalized. The result is not uniformly distributed on (0,1) anymore, but
instead is Dirichlet distributed with the parameters alpha. The Latin
properties are maintained.
require(lhs)
qdirichlet <- function(X, alpha)
{
# qdirichlet is not an exact quantile function since the quantile of a
# multivariate distribtion is not unique
# qdirichlet is also not the quantiles of the marginal distributions since
# those quantiles do not sum to one
# qdirichlet is the quantile of the underlying gamma functions, normalized
# This has been tested to show that qdirichlet approximates the dirichlet
# distribution well and creates the correct marginal means and variances
# when using a latin hypercube sample
lena <- length(alpha)
stopifnot(is.matrix(X))
sims <- dim(X)[1]
stopifnot(dim(X)[2] == lena)
if(any(is.na(alpha)) || any(is.na(X)))
stop("NA values not allowed in qdirichlet")
Y <- matrix(0, nrow=sims, ncol=lena)
ind <- which(alpha != 0)
for(i in ind)
{
Y[,i] <- qgamma(X[,i], alpha[i], 1)
}
Y <- Y / rowSums(Y)
return(Y)
}
X <- randomLHS(1000, 7)
Y <- qdirichlet(X, rep(1,7))
stopifnot(all(abs(rowSums(Y)-1) < 1E-12))
range(Y)
ws <- randomLHS(1000, 7)
wsSums <- rowSums(ws)
wss <- ws / wsSums
stopifnot(all(abs(rowSums(wss)-1) < 1E-12))
range(wss)
I hope this helps!
Rob
Rob Carnell
Battelle
Principal Research Scientist
More information about the R-help
mailing list