Last active
March 13, 2020 18:54
-
-
Save SigurdJanson/67f90a24d90f8769c4c0b4d39a82a421 to your computer and use it in GitHub Desktop.
Approximate a probability distribution function (PDF) from the moments
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#' polyPDF | |
#' This function constructs a PD function from the moments. The output of this function is the PDF. | |
#' @param moments data frame, containing the moment order ("n") in one column | |
#' and their values ("moments") in the other | |
#' @param xmin,xmax Lower and upper limit of the PDF. | |
#' @param scale Scale factor can be used to transform data avoiding singularity (default = 1). | |
#' @param disp If TRUE, the PDF will be plotted and the polynomial coefficients are shown. | |
#' @author Hugo Hernandez; small refactoring by Jan Seifert | |
#' @reference Hernandez, H. (2018). Comparison of Methods for the Reconstruction | |
#' of Probability Density Functions from Data Samples. Technical Report | |
#' @source https://t1p.de/wyhb | |
polyPDF <- function( moments, xmin = NULL, xmax = NULL, scale = 1, disp = FALSE) { | |
if (is.null(xmin) || is.null(xmax)) | |
stop("Please input 'xmin' and 'xmax' estimated values") | |
n <- length(moments$n) #Number of moments available | |
degree <- n-1 #Degree of polynomial | |
A <- matrix(0,n,n) #Initialize matrix of coefficients | |
B <- matrix(0,n,1) #Initialize vector of independent terms | |
for (i in 1:n) { #For each moment | |
ni <- moments$n[i] #ni-th moment | |
for (j in 1:n){ #For each power term | |
A[i,j] <- (((xmax*scale)^(ni+j))-((xmin*scale)^(ni+j)))/(ni+j) | |
} | |
B[i] <- moments$moments[i] * scale^ni #Scale moments | |
} | |
a <- as.vector(solve(A,B)) #Find coefficients | |
#Definition of PDF function | |
rhof <- function(x){ | |
rho <- a[1] #Independent term | |
for (i in 2:(degree+1)) { | |
rho <- rho + a[i] * (x*scale)^(i-1) #Polynomial terms | |
} | |
#Density is zero when rho is negative or X is beyond boundaries | |
rho <- rho * scale * as.integer(x>=xmin&x<=xmax) * as.integer(rho>0) | |
return(rho) | |
} #end of function | |
if (disp == TRUE) { | |
#Set coefficients names | |
names(a)[1:2]=c("(Intercept)","x") | |
if (length(a) > 2) { | |
for (i in 3:length(a)) { | |
names(a)[i] <- paste("x^", toString(i-1)) | |
} | |
} | |
print("Polynomial model of the PDF:") | |
print(a) | |
#PDF plot | |
i <- 1:1001 | |
y <- xmin + (xmax-xmin) * (i-1)/1000 | |
rho <- rhof(y) #Calculate density | |
plot(y,rho,type="l",col="blue",xlim=c(xmin,xmax),ylim=c(0,max(rho)), | |
xlab="Measurement values",ylab="Probability Density") | |
} | |
return(rhof) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment