Difference between revisions of "Opasnet (R library)"

From Testiwiki
Jump to: navigation, search
m
(Answer: updated functions and a couple of new ones)
Line 22: Line 22:
 
library(OpasnetBaseUtils)
 
library(OpasnetBaseUtils)
 
library(xtable)
 
library(xtable)
 +
 +
NIterations  <- 5
  
 
n <- 5
 
n <- 5
Line 188: Line 190:
 
# INTERPRET ################### interpret takes a vector and makes a data.frame out of it (to be used in e.g. make.ovariable).
 
# INTERPRET ################### interpret takes a vector and makes a data.frame out of it (to be used in e.g. make.ovariable).
 
### It also changes abbreviations into probability samples.
 
### It also changes abbreviations into probability samples.
interpret <- function(data) {
+
# Lognormal distribution parametrization functions
sample <- NULL
+
lmean <- function(parmean, parsd) {return(log(parmean)-log(1+(parsd^2)/(parmean^2))/2)}
if(is.vector(data)) {data <- data.frame(Result = data)}
+
lsd <- function(parmean, parsd) {return(log(1+(parsd^2)/(parmean^2)))}
if("Iter" %in% colnames(data)) {
+
 
out <- data}
+
# Actual interpretation function. Takes already pre-processed information and returns a distribution.
else {
+
interpf <- function(
if(!"Result" %in% colnames(data)) {cat("There MUST be an observation column named 'Result'.\n")}
+
n,
test <- !is.na(as.numeric(as.character(data$Result)))
+
res.char,
+
brackets.pos,
for(i in 1:nrow(data)) {
+
brackets.length,
if(test[i]) {
+
minus,
sample <- c(sample, rep(as.numeric(as.character(data[i, "Result"])), n))
+
minus.length,
 +
minus.exists,
 +
plusminus,
 +
plusminus.length,
 +
plusminus.exists,
 +
doublePoint
 +
) {
 +
 
 +
if(doublePoint[1] > 0) {
 +
tempArgs <- sort(as.numeric(unlist(strsplit(res.char, "\\:"))))
 +
return(rtriangle(n,tempArgs[1],tempArgs[3],tempArgs[2]))
 +
}
 +
if(brackets.pos >= 0) {
 +
minus.relevant <- unlist(minus)[(cumsum(c(0, minus.length)) + 1):cumsum(minus.length)]
 +
n.minus.inside.brackets <- sum(minus.relevant > brackets.pos & minus.relevant < brackets.pos + brackets.length)
 +
imean <- as.numeric(substr(res.char, 1, brackets.pos - 1))
 +
if(n.minus.inside.brackets == 1) {
 +
ici <- c(as.numeric(substr(res.char, brackets.pos + 1, minus.relevant[minus.relevant > brackets.pos] - 1)), as.numeric(substr(res.char,
 +
minus.relevant[minus.relevant > brackets.pos] + 1, brackets.pos + brackets.length - 2)))
 +
isd <- sum(abs(ici - imean) / 2) / qnorm(0.975)
 +
if((ici[2] - imean) / (ici[1] - imean) < 1.5) {
 +
return(rnorm(n, imean, isd))
 
} else {
 
} else {
samplingguide <- as.numeric(strsplit(gsub(" ", "", data[i, "Result"]), "-")[[1]])
+
return(out[[i]] <- rlnorm(n, lmean(imean, isd), lsd(imean, isd))) # menee vaarin koska isd on laskettu normaalijakaumalle
if(is.na(samplingguide[1]) | is.na(samplingguide[2])) {
+
}
sample <- c(sample, rep(data[i, "Result"], n))
+
} else
} else {
+
if(n.minus.inside.brackets %in% c(2,3)) {
sample <- c(sample, runif(n, samplingguide[1], samplingguide[2]))
+
ici <- c(as.numeric(substr(res.char, brackets.pos + 1, minus.relevant[minus.relevant > brackets.pos][2] - 1)), as.numeric(substr(res.char,
}
+
minus.relevant[minus.relevant > brackets.pos][2] + 1, brackets.pos + brackets.length - 2)))
 +
isd <- sum(abs(ici - imean) / 2) / qnorm(0.975)
 +
return(rnorm(n, imean, isd))
 +
}
 +
warning(paste("Unable to interpret \"", res.char, "\"", sep = ""))
 +
return(NA)
 +
}
 +
if(minus.exists) {
 +
minus.relevant <- unlist(minus)[(cumsum(c(0, minus.length)) + 1):cumsum(minus.length)]
 +
if(length(minus.relevant) == 1) {
 +
if(as.numeric(substr(res.char, 1, minus.relevant - 1)) / as.numeric(substr(res.char, minus.relevant + 1, nchar(res.char))) >= 1/100) {
 +
return(runif(n, as.numeric(substr(res.char, 1, minus.relevant - 1)), as.numeric(substr(res.char, minus.relevant + 1, nchar(res.char[i])))))
 +
} else {
 +
return(exp(runif(n, log(as.numeric(substr(res.char, 1, minus.relevant - 1))), log(as.numeric(substr(res.char, minus.relevant + 1, nchar(res.char)))))))
 
}
 
}
 
}
 
}
+
if(length(minus.relevant) %in% c(2,3)) {
out <- as.data.frame(array(1:(n*nrow(data)*(ncol(data)+1)), dim = c(n*nrow(data), ncol(data) + 1)))
+
return(runif(n, as.numeric(substr(res.char, 1, minus.relevant[2] - 1)), as.numeric(substr(res.char, minus.relevant[2] + 1, nchar(res.char)))))
colnames(out) <- c("Iter", colnames(data))
 
 
for(i in colnames(data)) {
 
out[i] <- rep(data[, i], each = n)
 
 
}
 
}
out$Iter <- 1:n
 
out$Result <- sample
 
 
 
}
 
}
return(out)
+
if(plusminus.exists) {
 +
return(rnorm(n, as.numeric(substr(res.char, 1, plusminus[1] - 1)), as.numeric(substr(res.char, plusminus[1] + 1, nchar(res.char)))))
 +
}
 +
if(sum(unlist(strsplit(res.char, ""))==";") > 0) {
 +
return(sample(sapply(strsplit(res.char, ";"), as.numeric), N, replace = TRUE))
 +
}
 +
warning(paste("Unable to interpret \"", res.char, "\"", sep = ""))
 +
return(NA)
 +
}
 +
 
 +
# The next function processes character strings and loops the interpretation function.
 +
input.interp <- function(res.char, n = 1000) {
 +
res.char <- gsub(" ", "", res.char)
 +
res.char <- gsub(",", ".", res.char)
 +
plusminus <- gregexpr(paste("\\+-|", rawToChar(as.raw(177)), sep = ""), res.char) # saattaa osoittautua ongelmaksi enkoodauksen vuoksi
 +
plusminus.length <- sapply(plusminus, length)
 +
plusminus.exists <- unlist(plusminus)[cumsum(c(0, plusminus.length[-length(plusminus.length)])) + 1] > 0
 +
minus <- gregexpr("-", res.char)
 +
minus.length <- sapply(minus, length)
 +
minus.exists <- unlist(minus)[cumsum(c(0, minus.length[-length(minus.length)])) + 1] > 0
 +
brackets <- gregexpr("\\(.*\\)", res.char) # matches for brackets "(...)"
 +
brackets.length <- as.numeric(unlist(sapply(brackets, attributes)[1,]))
 +
brackets.pos <- unlist(brackets)
 +
doublePoint <- gregexpr(":", res.char)
 +
out <- list()
 +
for(i in 1:length(res.char)) {
 +
out[[i]] <- interpf(n, res.char[i], brackets.pos[i], brackets.length[i], minus[i], minus.length[i], minus.exists[i], plusminus[[i]],
 +
plusminus.length[i], plusminus.exists[i],doublePoint[[i]])
 +
}
 +
out
 +
}
 +
 
 +
# Assisting function for data.frame wrapper.
 +
iter.f <- function(x) {
 +
1:x
 +
}
 +
 
 +
# Data.frame wrapper for the functions.
 +
interpret <- function(idata, rescol = "Result", N = 1000) {
 +
 
 +
temp <- input.interp(idata[, rescol], N)
 +
temp.lengths <- sapply(temp, length)
 +
out <- idata[rep(1:nrow(idata), times = temp.lengths),]
 +
out$Interp.Result <- unlist(temp)
 +
dim(temp.lengths) <- length(temp.lengths)
 +
out$Iter<- c(apply(temp.lengths, 1, iter.f))
 +
out
 
}
 
}
 +
 +
setGeneric("interpret")
 +
 +
setMethod(
 +
f = "interpret",
 +
signature = signature(idata = "character"),
 +
definition = function(idata) {
 +
if(!is.data.frame){
 +
callGeneric(data.frame(Result = idata))
 +
}
 +
callGeneric(idata)
 +
}
 +
)
  
 
# MAKE.OASSESSMENT ########## make.oassessment creates S4 assessment from dependencies data.frame, including decisions, stakeholders, probabilities, and variables.  
 
# MAKE.OASSESSMENT ########## make.oassessment creates S4 assessment from dependencies data.frame, including decisions, stakeholders, probabilities, and variables.  
Line 367: Line 455:
  
 
# SETCLASS OASSESSMENT ################### Defines the S4 class "oassessment" which is the object type for open assessments.
 
# SETCLASS OASSESSMENT ################### Defines the S4 class "oassessment" which is the object type for open assessments.
temp <- setClass(
+
setClass(
 
"oassessment",  
 
"oassessment",  
 
representation(
 
representation(
Line 379: Line 467:
  
 
# SETCLASS OVARIABLE ################### Defines the S4 class "ovariable" which is the basic building block in open assessments.
 
# SETCLASS OVARIABLE ################### Defines the S4 class "ovariable" which is the basic building block in open assessments.
temp <- setClass(
+
setClass(
 
"ovariable",  
 
"ovariable",  
 
representation(
 
representation(
name         = "character",
+
name = "character",
output       = "data.frame",  
+
output = "data.frame",  
data         = "data.frame",  
+
data = "data.frame",  
marginal     = "vector",  
+
marginal = "logical",  
formula     = "function",  
+
formula = "function",  
dependencies = "data.frame"
+
dependencies = "data.frame"
 +
),
 +
prototype = prototype(
 +
name = character(),
 +
output = data.frame(),
 +
data = data.frame(),
 +
marginal = logical(),
 +
formula = function(...){0},
 +
dependencies = data.frame()
 
)
 
)
 
)
 
)
Line 447: Line 543:
 
}
 
}
  
temp <- setGeneric("convert.units")
+
setGeneric("convert.units")
  
temp <- setMethod(
+
setMethod(
 
f = "convert.units",
 
f = "convert.units",
 
signature = signature(x = "ovariable"),
 
signature = signature(x = "ovariable"),
Line 461: Line 557:
 
)
 
)
  
temp <- setMethod(
+
setMethod(
 
f = "convert.units",
 
f = "convert.units",
 
signature = signature(x = "data.frame"),
 
signature = signature(x = "data.frame"),
Line 485: Line 581:
 
}
 
}
  
temp <- setGeneric("make.ovariable") # Makes make.ovariable a generic S4 function.
+
setGeneric("make.ovariable") # Makes make.ovariable a generic S4 function.
  
temp <- setMethod(
+
setMethod(
 
f = "make.ovariable",
 
f = "make.ovariable",
 
signature = signature(data = "data.frame"),
 
signature = signature(data = "data.frame"),
Line 501: Line 597:
 
)
 
)
  
temp <- setMethod(
+
setMethod(
 
f = "make.ovariable",
 
f = "make.ovariable",
 
signature = signature(data = "vector"),
 
signature = signature(data = "vector"),
Line 516: Line 612:
 
)
 
)
  
temp <- setMethod(
+
setMethod(
 
f = "make.ovariable",
 
f = "make.ovariable",
 
signature = signature(data = "list"),
 
signature = signature(data = "list"),
Line 532: Line 628:
 
)
 
)
  
temp <- setMethod(
+
setMethod(
 
f = "make.ovariable",
 
f = "make.ovariable",
 
signature = signature(data = "ovariable"),
 
signature = signature(data = "ovariable"),
Line 550: Line 646:
  
 
# SETMETHOD MATH ################### Math defines basic mathematical operations (log, exp, abs, ...) for ovariables
 
# SETMETHOD MATH ################### Math defines basic mathematical operations (log, exp, abs, ...) for ovariables
temp <- setMethod(
+
setMethod(
 
f = "Math",  
 
f = "Math",  
 
signature = signature(x = "ovariable"),  
 
signature = signature(x = "ovariable"),  
Line 560: Line 656:
  
 
# SETMETHOD MERGE ########### merge of ovariables merges the 'output' slot by index columns except 'Unit'.
 
# SETMETHOD MERGE ########### merge of ovariables merges the 'output' slot by index columns except 'Unit'.
temp <- setMethod(f = "merge",  
+
setMethod(f = "merge",  
 
signature = signature(x = "ovariable", y = "ovariable"),
 
signature = signature(x = "ovariable", y = "ovariable"),
 
definition = function(x, y) {
 
definition = function(x, y) {
Line 569: Line 665:
 
)
 
)
  
temp <- setMethod(f = "merge",  
+
setMethod(f = "merge",  
 
signature = signature(x = "ovariable", y = "numeric"),
 
signature = signature(x = "ovariable", y = "numeric"),
 
definition = function(x, y) {
 
definition = function(x, y) {
Line 577: Line 673:
 
)
 
)
  
temp <- setMethod(f = "merge",  
+
setMethod(f = "merge",  
 
signature = signature(x = "numeric", y = "ovariable"),
 
signature = signature(x = "numeric", y = "ovariable"),
 
definition = function(x, y) {
 
definition = function(x, y) {
Line 588: Line 684:
 
### then the operation is performed for the Result.x and Result.y columns.
 
### then the operation is performed for the Result.x and Result.y columns.
 
### If one of the expressions is numeric, it is first transformed to ovariable.
 
### If one of the expressions is numeric, it is first transformed to ovariable.
temp <- setMethod(
+
setMethod(
 
f = "Ops",  
 
f = "Ops",  
 
signature = signature(e1 = "ovariable", e2 = "ovariable"),  
 
signature = signature(e1 = "ovariable", e2 = "ovariable"),  
Line 601: Line 697:
 
)
 
)
  
temp <- setMethod(
+
setMethod(
 
f = "Ops",  
 
f = "Ops",  
 
signature = signature(e1 = "ovariable", e2 = "numeric"),  
 
signature = signature(e1 = "ovariable", e2 = "numeric"),  
Line 611: Line 707:
 
)
 
)
  
temp <- setMethod(
+
setMethod(
 
f = "Ops",  
 
f = "Ops",  
 
signature = signature(e1 = "numeric", e2 = "ovariable"),  
 
signature = signature(e1 = "numeric", e2 = "ovariable"),  
Line 623: Line 719:
 
# SETMETHOD PLOT ################ plot diagrams about ovariable data
 
# SETMETHOD PLOT ################ plot diagrams about ovariable data
  
temp <- setMethod(
+
setMethod(
 
f = "plot",
 
f = "plot",
 
signature = signature(x = "ovariable"),
 
signature = signature(x = "ovariable"),
Line 637: Line 733:
 
)
 
)
  
temp <- setMethod(
+
setMethod(
 
f = "plot",
 
f = "plot",
 
signature = signature(x = "oassessment"),
 
signature = signature(x = "oassessment"),
Line 649: Line 745:
 
# SETMETHOD PRINT ######################## print ovariable contents
 
# SETMETHOD PRINT ######################## print ovariable contents
  
temp <- setMethod(
+
setMethod(
 
f = "print",
 
f = "print",
 
signature = signature(x = "oassessment"),
 
signature = signature(x = "oassessment"),
Line 670: Line 766:
 
)
 
)
  
temp <- setMethod(
+
setMethod(
 
f = "print",
 
f = "print",
 
signature = signature(x = "ovariable"),
 
signature = signature(x = "ovariable"),
Line 686: Line 782:
 
# SETMETHOD UPDATE ########## update updates the output of an ovariable based on data and function.
 
# SETMETHOD UPDATE ########## update updates the output of an ovariable based on data and function.
 
####### The function assumes that object@data is always available, but object@dependencies may be empty.
 
####### The function assumes that object@data is always available, but object@dependencies may be empty.
temp <- setMethod(
+
setMethod(
 
f = "update",  
 
f = "update",  
 
signature = "ovariable",  
 
signature = "ovariable",  
Line 769: Line 865:
 
### X an ovariable
 
### X an ovariable
  
temp <- setMethod(f = "tapply",  
+
setMethod(f = "tapply",  
 
signature = signature(X = "ovariable"),
 
signature = signature(X = "ovariable"),
 
definition = function(X, INDEX, FUN = NULL, ..., simplify = TRUE) {
 
definition = function(X, INDEX, FUN = NULL, ..., simplify = TRUE) {
Line 781: Line 877:
 
# TIDY ########### tidy: a function that cleans the tables from Opasnet Base
 
# TIDY ########### tidy: a function that cleans the tables from Opasnet Base
 
# data is a table from op_baseGetData function
 
# data is a table from op_baseGetData function
tidy <- function (data, idvar = "obs", direction = "wide") {
+
# TIDY ########### tidy: a function that cleans the tables from Opasnet Base
 
+
# data is a table from op_baseGetData function
data$Result <- ifelse(!is.na(data$Result.Text), as.character(data$Result.Text), data$Result)
+
tidy <- function (data, objname = "", idvar = "obs", direction = "wide") {
if("Observation" %in% colnames(data)){test <- data$Observation != "Description"} else {test <- TRUE}
+
data$Result <- ifelse(!is.na(data$Result.Text), data$Result, as.character(data$Result.Text))
data <- data[test, !colnames(data) %in% c("id", "Result.Text")]
+
#data <- data[
if("obs.1" %in% colnames(data)) {data[, "obs"] <- data[, "obs.1"]} # this line is temporarily needed until the obs.1 bug is fixed.
+
# ifelse("Observation" %in% colnames(data),
data <- data[colnames(data) != "obs.1"]
+
# data$Observation != "Description",
 +
# TRUE
 +
# ),
 +
# !colnames(data) %in% c("id", "Result.Text")
 +
#]
 +
data <- data[, !colnames(data) %in% c("id", "Result.Text")]
 +
if("obs.1" %in% colnames(data)) { # this line is temporarily needed until the obs.1 bug is fixed.
 +
data[, "obs"] <- data[, "obs.1"]
 +
data <- data[, colnames(data) != "obs.1"]
 +
}
 
if("Row" %in% colnames(data)) { # If user has given Row, it is used instead of automatic obs.
 
if("Row" %in% colnames(data)) { # If user has given Row, it is used instead of automatic obs.
 
data <- data[, colnames(data) != "obs"]
 
data <- data[, colnames(data) != "obs"]
 
colnames(data)[colnames(data) == "Row"] <- "obs"
 
colnames(data)[colnames(data) == "Row"] <- "obs"
 
}
 
}
if(direction == "wide" & "Observation" %in% colnames(data))  
+
if (objname != "") objname <- paste(objname, ":", sep = "")
{
+
if (direction == "wide") {
data <- reshape(data, idvar = idvar, timevar = "Observation", v.names = "Result", direction = "wide")
+
if("Observation" %in% colnames(data)) {
data <- data[colnames(data) != "obs"]
+
cols <- levels(data$Observation)
colnames(data) <- gsub("^Result.", "", colnames(data))
+
data <- reshape(data, idvar = idvar, timevar = "Observation", v.names = "Result", direction = "wide")
colnames(data)[colnames(data) == "result"] <- "Result"
+
data <- data[colnames(data) != "obs"]
colnames(data)[colnames(data) == "Amount"] <- "Result"
+
colnames(data) <- gsub("^Result.", objname, colnames(data))
 +
for (i in paste(objname, cols, sep = "")) {
 +
a <- suppressWarnings(as.numeric(data[, i]))
 +
if (sum(is.na(a)) == 0) data[, i] <- a else data[, i] <- factor(data[, i])
 +
}
 +
colnames(data)[grepl(paste("^", objname, "result", sep = ""), colnames(data))] <- paste(objname, "Result", sep = "")
 +
colnames(data)[grepl(paste("^", objname, "Amount", sep = ""), colnames(data))] <- paste(objname, "Result", sep = "")
 +
return(data)
 +
}
 +
if("Parameter" %in% colnames(data)) {
 +
cols <- levels(data$Parameter)
 +
data <- reshape(data, idvar = idvar, timevar = "Parameter", v.names = "Result", direction = "wide")
 +
data <- data[colnames(data) != "obs"]
 +
colnames(data) <- gsub("^Result.", objname, colnames(data))
 +
for (i in paste(objname, cols, sep = "")) {
 +
a <- suppressWarnings(as.numeric(data[, i]))
 +
if (sum(is.na(a)) == 0) data[, i] <- a else data[, i] <- factor(data[, i])
 +
}
 +
colnames(data)[grepl(paste("^", objname, "result", sep = ""), colnames(data))] <- paste(objname, "Result", sep = "")
 +
colnames(data)[grepl(paste("^", objname, "Amount", sep = ""), colnames(data))] <- paste(objname, "Result", sep = "")
 +
return(data)
 +
}
 +
}
 +
data <- data[,colnames(data) != "obs"]
 +
colnames(data)[colnames(data)=="Result"] <- paste(objname, "Result", sep = "")
 +
return(data)
 +
}
 +
 
 +
# FETCH ##################### fetch downloads a variable.
 +
 
 +
fetch <- function(x, direction = "wide") { # Could think of a version where dependencies table is given as a parameter, and based on Name, Identifier is downloaded from the Base.
 +
x <- as.character(x)
 +
if(exists(x)) {
 +
out <- get(x)
 +
} else {
 +
out <- tidy(op_baseGetData("opasnet_base", x), direction = "wide")
 +
}
 +
return(out)
 +
}
 +
 
 +
 
 +
# Fetch2 #################### loads all given dependencies to global memory
 +
 
 +
Fetch2 <- function(dependencies, evaluate = FALSE) {
 +
for (i in 1:nrow(dependencies)) {
 +
if(!exists(dependencies$Name[i])) {
 +
objects.get(dependencies$Key[i]) # Key is the R-tools session identifier (shown at the end of the url)
 +
if (evaluate) get(dependencies$Name[i])@output <- EvalOutput(get(dependencies$Name[i]))
 +
# Eval not necessarily needed at this point
 +
cat()
 +
}
 +
}
 +
} # no need to return anything since variables are already written in global memory
 +
 
 +
#library(reshape2)
 +
#library(reshape) # for older version
 +
 
 +
# EvalOutput #################### evaluates the output slot of ovariables
 +
##### Marginals should be also checked and updated here or elsewhere
 +
 
 +
EvalOutput <- function(variable, ...) { # ... for e.g na.rm
 +
#if (nrow(variable@data) > 0) { # if interpret can handle zero rows, no problem
 +
#if (!exists("rescol")) # doesn't work when rescol given in '...' arguments; rescol is used in interpreting data
 +
rescol <- ifelse(
 +
"Result" %in% colnames(variable@data),
 +
"Result",
 +
paste(variable@name, "Result", sep = ":")
 +
)
 +
if (!is.numeric(variable@data[[rescol]])) {
 +
a <- interpret(variable@data, rescol = rescol, N = NIterations, ...)
 +
} else a <- variable@data
 +
#}
 +
b <- variable@formula(variable@dependencies)
 +
if (b == 0 & nrow(variable@data) == 0) {
 +
stop(paste("No proper data nor formula defined for ", variable@name, "!\n", sep = ""))
 +
}
 +
if (b == 0) {
 +
a[,paste(variable@name, "Source", sep = ":")] <- "Data"
 +
return(a)
 +
}
 +
if (nrow(variable@data) == 0) {
 +
b[,paste(variable@name, "Source", sep = ":")] <- "Formula"
 +
return(b)
 +
}
 +
colnames(a)[colnames(a) == rescol] <- "FromData"
 +
colnames(b)[colnames(b) %in% c(paste(variable@name, "Result", sep = ":"), "Result")] <- "FromFormula" # *
 +
# <variablename>: prefix not necessitated for "Result" column of formula output
 +
temp <- melt(
 +
merge(a, b, all = TRUE, ...), # Will cause problems if dependencies contain non-marginal indices that match with -
 +
# marginal indeces in data. Or maybe not.
 +
measure.vars = c("FromData", "FromFormula"),
 +
variable.name = paste(variable@name, "Source", sep = ":"),
 +
value.name = paste(variable@name, "Result", sep = ":"),
 +
...
 +
)
 +
levels(
 +
temp[[paste(variable@name, "Source", sep = ":")]]
 +
) <- gsub("^From", "",
 +
levels(
 +
temp[[paste(variable@name, "Source", sep = ":")]]
 +
)
 +
)
 +
return(temp)
 +
}
 +
 
 +
# CheckMarginals ############# Assumes that all depended upon variables are in memory, as should be the case.
 +
##################
 +
# Returns a marginal devised from the data and upstream variable marginals.
 +
# Marginal values for data should be stored into the database somehow
 +
 
 +
CheckMarginals <- function(variable) {
 +
varmar <- colnames(variable@data)[
 +
,
 +
!grepl(paste("^", variable@name, ":", sep=""), colnames(variable@data))&
 +
!colnames(variable@data) %in% c("Result", "Unit")
 +
]
 +
# all locs under observation/parameter index should be excluded
 +
varmar <- c(varmar, paste(variable@name, "Source", sep = "_")) # Source is usually added
 +
# by EvalOutput so it should be in the initial list by default.
 +
norvarpmar <- colnames(variable@data)[!colnames(variable@data) %in% varmar]
 +
for (i in variable@dependencies$Name){
 +
varmar <- unique(varmar, colnames(get(i)@output)[get(i)@marginal])
 +
novarmar <- unique(novarmar, colnames(get(i)@output)[!get(i)@marginal])
 +
}
 +
varmar <- varmar[!varmar %in% novarmar]
 +
return(colnames(variable@output) %in% varmar)
 +
}
 +
 
 +
#marginal <- ifelse(colnames(output) %in% c("Result", "Unit"), FALSE, TRUE)
 +
 
 +
# CheckInput ################# checks and uses outside input (user inputs in models or decision variables)
 +
# takes an ovariable as argument, output
 +
# returns an ovariable
 +
 
 +
CheckInput <- function(variable, substitute = FALSE, ...) { # ... e.g for na.rm
 +
if (nrow(variable@output) == 0) stop(paste(variable@name, "output not evaluated yet!"))
 +
if (exists(paste("Inp", variable@name, sep = ""))) {
 +
inputvar <- get(paste("Inp", variable@name, sep = ""))
 +
if (substitute) {
 +
colnames(inputvar@output)[colnames(inputvar@output) == paste(inputvar@name, "Result", sep = ":")] <- "InpVarRes"
 +
colnames(variable@output)[colnames(variable@output) == paste(variable@name, "Result", sep = ":")] <- "VarRes"
 +
finalvar <- merge(variable, inputvar)
 +
finalvar@output[[paste(variable@name, "Result", sep = ":")]] <- ifelse(
 +
is.na(finalvar@output$InpVarRes),
 +
finalvar@output$VarRes,
 +
finalvar@output$InpVarRes
 +
)
 +
finalvar@output[[paste(variable@name, "Source", sep = ":")]] <- ifelse(
 +
is.na(finalvar@output$InpVarRes),
 +
finalvar@output[[paste(variable@name, "Source", sep = ":")]],
 +
"Input"
 +
)
 +
return(finalvar[!colnames(finalvar) %in% c("InpVarRes", "VarRes")])
 +
}
 +
#variable@output[variable@output$Source,]
 +
j <- levels(variable@output[[paste(variable@name, "Source", sep = ":")]])
 +
temp <- variable@output[
 +
variable@output[,paste(variable@name, "Source", sep = ":")] == j[1],
 +
!colnames(variable@output) %in% paste(variable@name, "Source", sep = ":")
 +
]
 +
colnames(temp)[colnames(temp) %in% "Result"] <- j[1]
 +
for (i in j[!j == j[1]]) {
 +
temp <- merge(
 +
temp,
 +
variable@output[
 +
variable@output[,paste(variable@name, "Source", sep = ":")] == i,
 +
!colnames(variable@output) %in% paste(variable@name, "Source", sep = ":")
 +
]
 +
)
 +
colnames(temp)[colnames(temp) %in% "Result"] <- i
 +
}
 +
return(
 +
melt(
 +
temp,
 +
measure.vars = levels(variable@output[,paste(variable@name, "Source", sep = ":")]),
 +
variable.name = paste(variable@name, "Source", sep = ":"),
 +
value.name = paste(variable@name, "Result", sep = ":"),
 +
...
 +
)
 +
)
 
}
 
}
else
+
#cat("No input found for ", variable@name, ". Continuing...\n")
{
+
return(variable@output)
data <- data[colnames(data) != "obs"]
+
}
 +
 
 +
# ComputeDependencies ############ uses Fetch2, EvalOutput, CheckMarginals and CheckInput to load and pre-process
 +
# upstream variables. Typically seen on the first line of ovariable formula code.
 +
 
 +
ComputeDependencies <- function(dependencies) {
 +
Fetch2(dependencies)
 +
for (i in dependencies$Name) {
 +
get(i)@output <- EvalOutput(get(i))
 +
get(i)@marginals <- CheckMarginals(get(i))
 +
get(i)@output <- CheckInput(get(i))
 
}
 
}
return(data)
 
 
}
 
}
 +
  
 
</rcode>
 
</rcode>

Revision as of 12:57, 20 June 2012


--# : The page should be renamed. OpasnetUtils is the current name of the R package containing these and the old OpasnetBaseUtils functions. --Teemu R 11:23, 14 June 2012 (EEST)


This is a library of functions for R statistical software, designed for the key tasks of modelling in Opasnet.

Question

What functions should be used in Opasnet modelling?

Answer

+ Show code

# : There is a bug somewhere that changes the case of initial letters in locations (values of indices). For example these unwanted conversions have been seen: Result -> result, Type -> type, g -> G, m -> M, p -> P. This happens when the data is uploaded to Opasnet Base, because the wrong case is seen both with op_baseGetData and Opasnet Base interface. Example data with problems: Unit conversions. --Jouni 11:44, 3 June 2012 (EEST)

# : This is a problem of the MySQL database. When determining loc.id:s, the op_baseWrite function queries the database for existing locations of the same name (after first issuing an error-ignoring query for entering all the indices and locations in the data). Since SQL is not caste sensitive for the first letter (thats what I believe caused some issues earlier) it will consider "Result" and "result" equal and will not allow both to be entered into the database as separate unique values. Hence when uploaded data contains a location or index "Result" and the database already contains an entry "result", "Result" cannot be entered. But R is case sensitive and will not recognize the returned value of "result" as the same as "Result" in the data. So to circumvent this issue all entries that are returned for matching are converted to lower case. So to fix this issue you would have to correct the old entry for the location "result" to "Result" in the database or make sure to be very careful that new indices and locations (when created) are in the proper case as all following uploads will use the same format. --Teemu R 14:00, 3 June 2012 (EEST)
TODO: {{#todo:Poistuuko tämä ongelma Opasnet Base 2:ssa?|Juha Villman, Einari Happonen|}}


TODO: {{#todo:Toinen asia OB2:een liittyen: Indekseille pitäisi pystyä antamaan yksiköt, koska ne eivät ole itsestäänselviä (Erkki huomasi tämän). Onko tämän toteutus suunniteltu? Seka kannassa pitää olla paikka, ja lisäksi esim. t2b:ssa olisi syytä olla parametri yksiköiden antamista varten (tai pitäisikö nykyistä unit-parametrin käyttöä laajentaa?).|Juha Villman, Einari Happonen|}}


Rationale

These functions were previously on pages

See also

References


Related files

<mfanonymousfilelist></mfanonymousfilelist>