# Structure of objects
#
# Abstract object: geom:
#
# curve gcurve
# marker gcurve
# point gpoint
# area garea
#' plot a single curve in a pane
plot.curve = function(curve=NULL, eq=NULL,pane, main=NULL, label="", ...) {
eq = substitute(eq)
restore.point("plot.curve")
if (is.null(curve)) {
curve = init.curve(name="curve", eq=eq, xvar=pane$xvar, yvar=pane$yvar, label=label, ...)
}
geoms = objects.to.geoms(list(curve), pane=pane)
plot.pane(pane, geoms=geoms,main = main)
}
example.plot.pane = function() {
opc.pane = pane(xvar="u",yvar="dw",xlab="Arbeitslosigkeitsquote (u)", ylab="Relative Lohnsteigerung", xrange=c(0,0.2), yrange=c(-0.1,0.2))
plot.curve(eq = (dw ==-0.1 + 1.1*u), pane=opc.pane, color="blue", main="Hypothese 1")
abline(h=0)
yaml = '
pane:
curves:
demand:
label: D{{idD}}
eq: y == A - b *p
color: red
supply:
label: S{{idS}}
eq: p == mc
color: blue
xy: [y,p]
xrange: [0,100]
yrange: [0,150]
xmarkers: [y_eq]
ymarkers: [p_eq]
'
pane = init.yaml.pane(yaml=yaml)
pane$params = list(A=100, b=1, mc=20,y_eq=30, p_eq=40, idD=1,idS="")
make.pane.data(pane)
compute.pane.geoms(pane)
plot.pane(pane)
res = locator(1)
}
#' Plot a pane
plot.pane = function(pane, show = pane$show, hide=pane[["hide"]], xrange=pane$xrange, yrange=pane$yrange, alpha=1,main="",mar=NULL, show.grid=!TRUE, label.df=NULL,lwd.factor=1,label.cex=0.75, cex.axis=0.8,
xlab= if (is.null(pane$xlab)) pane$xvar else pane$xlab,
ylab= if (is.null(pane$ylab)) pane$yvar else pane$ylab,
compute.geoms=TRUE, params = pane$params, data=pane$data, data_rows=1
) {
restore.point("plot.pane")
pane$data = data
pane$params = params
pane$yrange = yrange
pane$xrange = xrange
data_rows = unlist(data_rows)
missing.cols = check.for.missing.data.cols(pane,pane$data, show=show)
if (compute.geoms)
compute.pane.geoms(pane=pane,data_rows=data_rows)
if (is.null(mar)) {
mar = c(4,3,1,1)
if (is.null(main)) mar[3] = 0
}
par(mar=mar)
plot.empty.pane(xlim=xrange, ylim=yrange,mar=mar,xlab=xlab,ylab=ylab,main=main, show.grid=show.grid, cex.axis=cex.axis)
geoms = NULL
i = 1
if (identical(show,".all")) {
show = names(pane$objs)
}
for (i in seq_along(data_rows)) {
row = data_rows[i]
if (is.list(show)) {
cur.show = show[[i]]
} else {
cur.show = show
}
if (is.list(hide)) {
cur.show = setdiff(cur.show, hide[[i]])
} else {
cur.show = setdiff(cur.show, hide)
}
cur.geoms = pane$geoms.li[[row]][cur.show]
geoms = c(geoms, cur.geoms)
}
if (is.null(geoms)) {
cat("\nNo geoms drawn...")
return()
}
draw.geoms(geoms,lwd.factor=lwd.factor)
if (is.null(label.df))
label.df = find.label.pos(geoms,xrange = pane$xrange, yrange=pane$yrange)
boxed.labels(x = label.df$x,y = label.df$y,labels = label.df$label,cex=label.cex,bg="white",border=FALSE,xpad=1.1,ypad=1.1)
pane$geoms = geoms
invisible(pane)
}
#' Compute concrete geoms for all objects of a pane
#'
#' @pane the pane object
#' @values a list of values used to evaluate the object formulas to compute the geoms
#' @values objs by default all objects of the pane, but alternatively, other objects can be provided
#' @xrange the x-axis range on which geoms shall be computed (default is pane$xrange)
#' @yrange the y-axis range on which geoms shall be computed (default is pane$yrange)
#' @name.prefix a prefix added to object names (useful if we have several geoms per object computed from different values)
#' @name.postfix a postfix added to object names (useful if we have several geoms per object computed from different values)
#' @label.prefix a prefix added to object label (useful if we have several geoms per object computed from different values)
#' @label.postfix a postfix added to object label (useful if we have several geoms per object computed from different values)
compute.pane.geoms = function(pane, data_rows = 1, objs = pane$objs, overwrite = TRUE) {
restore.point("computer.pane.geoms")
if (isTRUE(pane$data_xrange))
pane$xrange = compute.pane.range.from.data(pane=pane,ax="x", data_rows=data_rows)
if (isTRUE(pane$data_yrange))
pane$yrange = compute.pane.range.from.data(pane,"y", data_rows)
if (is.null(names(data_rows)))
names(data_rows) = data_rows
for (i in seq_along(data_rows)) {
r = data_rows[[i]]
if (!overwrite) {
if (!is.null(pane$geoms.li[[r]])) next
}
values = c(as.list(pane$data[r,]), list(.row=r, .role=names(data_rows)[i]))
pane$geoms.li[[r]] = objects.to.geoms(objs=objs, values=values, pane=pane, data_row=r)
}
}
compute.pane.range.from.data = function(pane, ax="x", data_rows) {
restore.point("compute.pane.range.from.data")
data = pane$data
vars = names(data)
var = pane[[paste0(ax,"var")]]
minvar = paste0(var,"_min")
maxvar = paste0(var,"_max")
addrange = pane[[paste0("add_",ax,"range")]]
if (!minvar %in% vars) {
stop(paste0("The pane ", pane$name, " has not specified the ",ax,"range and neither does its data contain the variable ", minvar, ", which could be used to compute the range."))
}
if (!maxvar %in% vars) {
stop(paste0("The pane ", pane$name, " has not specified the ",ax,"range and neither does its data contain the variable ", maxvar, ", which could be used to compute the range."))
}
start = min(data[[minvar]][data_rows])
end = max(data[[maxvar]][data_rows])
start = start - (end-start)*addrange[1]
end = end + (end-start)*addrange[2]
c(start,end)
}
does.geom.change.with.data.row = function(data_rows,obj=geom$obj, data=pane$data, pane=NULL, geom=NULL) {
parnames =
len = sapply(obj$parnames, function(par) {
length(unique(data[[par]][data_rows]))
})
any(len>0)
}
do.geoms.differ.across.rows = function(pane, data_rows, objs=pane$objs) {
data = pane$data
lapply(seq_along(objs), function(oi) {
obj = objs[[oi]]
parnames = obj$parnames
})
for (oi in seq_along(objs)) {
}
}
#' Compute concrete geoms for all objects of a pane
#'
#' @pane the pane object
#' @values a list of values used to evaluate the object formulas to compute the geoms
#' @values objs by default all objects of the pane, but alternatively, other objects can be provided
#' @xrange the x-axis range on which geoms shall be computed (default is pane$xrange)
#' @yrange the y-axis range on which geoms shall be computed (default is pane$yrange)
#' @name.prefix a prefix added to object names (useful if we have several geoms per object computed from different values)
#' @name.postfix a postfix added to object names (useful if we have several geoms per object computed from different values)
#' @label.prefix a prefix added to object label (useful if we have several geoms per object computed from different values)
#' @label.postfix a postfix added to object label (useful if we have several geoms per object computed from different values)
old.compute.pane.geoms = function(pane, objs = pane$objs,xrange=pane$xrange, yrange=pane$yrange,name.prefix=rep("",nr), name.postfix=rep("",nr), label.prefix=rep("",nr), label.postfix=rep("",nr), params=pane$params, data = pane$data, data_rows = NULL, color.level=rep(1,nr), nr=max(1,length(data_rows)), compute.data = FALSE, ...) {
restore.point("computer.pane.geoms")
if (is.null(values)) {
values = params
}
if (is.null(data_rows) | length(data_rows)==1) {
geoms = objects.to.geoms(objs=objs, values=values, xrange = xrange,yrange=yrange, name.prefix=name.prefix, name.postfix=name.postfix, label.prefix=label.prefix, label.postfix=label.postfix,color.level=color.level,...)
} else {
geoms.li = lapply(seq_along(data_rows), function(i) {
objects.to.geoms(objs=objs, values=values, xrange = xrange,yrange=yrange, name.prefix=name.prefix[i], name.postfix=name.postfix[i], label.prefix=label.prefix[i], label.postfix=label.postfix[i],color.level=color.level[i],...)
})
geoms = do.call("c", geom.li)
}
geoms
}
pane = function(...) as.environment(init.pane(...))
#' Initilize a pane
init.pane = function(pane=list(),name=NULL, xvar=NULL, yvar=NULL, xrange=NULL, yrange=NULL, xaxis=list(), yaxis=list(), xmarkers=NULL, ymarkers=NULL, geoms.li=NULL, curves=NULL, init.curves=TRUE, data=NULL, params=NULL, datavar=NULL, use_dataenv_directly = FALSE, data_roles =NULL, show=".all", hide=NULL, xlen=201,ylen=201, org.width = 420, org.height=300, margins=pane$margins, init.data=FALSE, dataenv=parent.frame(), data_xrange=NA , data_yrange=NA, add_xrange = c(0, 0), add_yrange=c(0, 0.1)) {
restore.point("init.pane")
pane = as.list(pane)
pane$org.li = pane
pane = copy.into.null.fields(dest=pane, source=nlist(name,xvar, yvar,xrange,yrange, curves, xmarkers, ymarkers, geoms.li, xaxis, yaxis, params, datavar, use_dataenv_directly, data_roles, show, hide,xlen,ylen, add_xrange, add_yrange, data_xrange, data_yrange))
if (is.null(pane$xaxis)) pane$xaxis = list()
if (is.null(pane$yaxis)) pane$yaxis = list()
pane$xaxis = copy.into.null.fields(dest=pane$xaxis, source=list(show.ticks=first.non.null(pane$show.ticks,TRUE),label=pane$xlab))
pane$yaxis = copy.into.null.fields(dest=pane$yaxis, source=list(show.ticks=first.non.null(pane$show.ticks,TRUE),label=pane$ylab))
pane$xaxis = copy.into.null.fields(dest=pane$xaxis, source=list(show.tick.labels=first.non.null(pane$show.tick.labels,pane$xaxis$show.ticks)))
pane$yaxis = copy.into.null.fields(dest=pane$yaxis, source=list(show.tick.labels=first.non.null(pane$show.tick.labels,pane$yaxis$show.ticks)))
if (is.na(pane$data_xrange)) pane$data_xrange = is.null(pane$xrange)
if (is.na(pane$data_yrange)) pane$data_yrange = is.null(pane$yrange)
if (is.null(margins)) {
margins = c(bottom=60,left=60, top=20, right=20)
if (!isTRUE(pane$yaxis$show.ticks))
margins["left"] = 40
if (!isTRUE(pane$xaxis$show.ticks))
margins["bottom"] = 40
}
pane$margins=margins
pane = as.environment(pane)
if (is.null(pane[["name"]]))
pane$name = attr(pane,"name")
if (!is.null(pane[["xy"]])) {
if (is.null(pane$xvar))
pane$xvar = pane$xy[1]
if (is.null(pane$yvar))
pane$yvar = pane$xy[2]
}
if (!is.null(pane$curves) & init.curves) {
curve.names = names(pane$curves)
pane$curves = lapply(seq_along(pane$curves), function(i) {
init.curve(name=curve.names[i], xvar=pane$xvar, yvar=pane$yvar, curve=pane$curves[[i]])
})
names(pane$curves) = curve.names
}
pane$points = init.pane.points(pane)
pane$markers= init.pane.markers(pane)
pane$objects = init.pane.objects(pane)
pane$objs = c(pane$curves, pane$markers, pane$points, pane$objects)
pane$parnames =unique(unlist(lapply(pane$objs, function(obj) obj$parnames)))
if (!is.null(pane$vars)) {
library(EconModels)
make.pane.model(pane)
}
pane$org.width = org.width
pane$org.height = org.height
pane$margins = margins
if (init.data)
pane$data = make.pane.data(pane=pane, dataenv=dataenv)
pane
}
update.pane.objs = function(pane, curves=NULL, points=NULL,xmarkers = NULL, ymarkers=NULL, objects=NULL) {
restore.point("update.pane.objs")
if (is.null(curves) & is.null(points) & is.null(xmarkers) & is.null(ymarkers) & is.null(objects)) {
return(pane)
}
if (!is.null(curves)) {
if (is.null(pane$curves)) pane$curves = list()
curve.names = names(curves)
pane$curves[curve.names] = lapply(seq_along(curves), function(i) {
restore.point("dfhdfufhriu")
if (curve.names[i] %in% names(pane$org.li$curves)) {
curve = copy.into.nested.list(pane$org.li$curves[curve.names[i]],new = curves[i])[[1]]
} else {
curve = curves[[i]]
}
init.curve(name=curve.names[i], xvar=pane$xvar, yvar=pane$yvar, curve=curve)
})
}
if (!is.null(points)) {
restore.point("update.pane.points")
if (is.null(pane[["points"]]))
pane$points =list()
pane$points[names(points)] = lapply(names(points), function(name) {
init.point(obj=points[[name]],name=name,pane = pane)
})
}
names_markers = c(names(xmarkers),names(ymarkers))
xmarkers = lapply(names(xmarkers), function(name) {
init.marker(xmarkers[[name]],name=name, axis="x", pane=pane)
})
ymarkers = lapply(names(ymarkers), function(name) {
init.marker(ymarkers[[name]],name=name, axis="y", pane=pane)
})
markers = c(xmarkers,ymarkers)
names(markers)= names_markers
pane$markers[names(markers)] = markers
if (!is.null(objects)) {
restore.point("update.pane.objects")
if (is.null(pane[["objects"]]))
pane$objects =list()
pane$objects[names(objects)] = lapply(names(objects), function(name) {
init.object(obj=objects[[name]],name=name,pane = pane)
})
}
pane$objs = c(pane$curves, pane$markers, pane$points, pane$objects)
pane$parnames =unique(unlist(lapply(pane$objs, function(obj) obj$parnames)))
pane
}
#' Initialize a pane specified with yaml code
init.yaml.pane = function(yaml=NULL, pane=NULL,name=NULL, direct=FALSE, init.data=FALSE) {
restore.point("init.yaml.pane")
if (is.null(pane)) {
li = read.yaml(text=yaml)
if (!direct) {
pane = li[[1]]
if (is.null(pane$name))
pane$name = names(li)[1]
} else {
pane = li
if (is.null(name)) name = "pane"
pane$name = name
}
}
pane$xrange = unlist(pane$xrange)
pane$yrange = unlist(pane$yrange)
pane$data_rows = unlist(pane$data_rows)
pane = init.pane(pane=pane, dataenv = parent.frame())
pane
}
has.pane.all.symbols = function(pane, symbols) {
restore.point("has.pane.all.symbols")
pane.symbols = c(pane$curves,names(pane$markers))
lag = symbols[str.starts.with(symbols,"lag_")]
lag.base = str.right.of(lag, "lag_")
cur = setdiff(symbols,lag)
if (!all(lag.base %in% pane.symbols)) return(FALSE)
if (!all(cur %in% pane.symbols)) return(FALSE)
return(TRUE)
}
make.pane.data = function(pane=NULL,params=pane$params, priority_params = pane$priority_params, data=pane$data, datavar = pane$datavar, dataenv = pane$dataenv, use_dataenv_directly = pane$use_dataenv_directly, parnames = pane$parnames, warn.missing.param, compute.model=TRUE) {
restore.point("make.pane.data")
# fetch datavar from dataenv
if (is.null(data) & !is.null(dataenv) & !is.null(datavar)) {
data = dataenv[[datavar]]
}
if (is.null(data) | NROW(data)==0) data = list()
# copy params into data
cols = setdiff(names(params),names(data))
data[cols] = params[cols]
# copy values from dataenv into data
if (isTRUE(use_dataenv_directly) & (!is.null(dataenv))) {
cols = setdiff(ls(dataenv),names(data))
for (col in cols) {
data[[col]] = dataenv[[col]]
}
}
# copy priority_params
cols = names(priority_params)
data[cols] = priority_params
data = as.data.frame(data,stringsAsFactors = FALSE)
if (isTRUE(pane$has.model) & compute.model & NROW(data)>0) {
var.mat = pane$em$sim.fun(data)
data = cbind(data, as.data.frame(var.mat))
}
data = as_data_frame(data)
if (!is.null(pane)) pane$data = data
invisible(data)
}
check.for.missing.data.cols = function(pane,data, show.warning=TRUE, show=".all") {
restore.point("check.for.missing.data.cols")
parnames = pane$parnames
if (!identical(show,".all")) {
parnames = intersect(parnames, unlist(show))
}
missing.cols = setdiff(pane$parnames, names(data))
if (length(missing.cols)>0 & show.warning) {
msg = paste0("\nThe required data columns ", paste0(missing.cols, collapse = ", "), " are missing.")
message("Warning: ",msg)
}
missing.cols
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.