addOBV throwing error - r

I am trying to plot a graph with price and a few technical indicators such as ADX, RSI, and OBV. I cannot figure out why addOBV is giving an error and why addADX not showing at all in the graph lines in the chart?
Here my code:
tmp <- read.csv(paste("ProcessedQuotes/",Nifty[x,],".csv", sep=""),
as.is=TRUE, header=TRUE, row.names=NULL)
tmp$Date<-as.Date(tmp$Date)
ydat = xts(tmp[,-1],tmp$Date)
lineChart(ydat, TA=NULL, name=paste(Nifty[x,]," Technical Graph"))
plot(addSMA(10))
plot(addEMA(10))
plot(addRSI())
plot(addADX())
plot(addOBV())
Error for addOBV is:
Error in try.xts(c(2038282, 1181844, -1114409, 1387404, 3522045, 4951254, :
Error in as.xts.double(x, ..., .RECLASS = TRUE) :
order.by must be either 'names()' or otherwise specified
Below you can see DIn is not shown fully in the graphs.
> class(ydat)
[1] "xts" "zoo"
> head(ydat)
Open High Low Close Volume Trades Sma20 Sma50 DIp DIn DX ADX aroonUp aroonDn oscillator macd signal RSI14

I don't know why that patch doesn't work for you, but you can just create a new function (or you could mask the one from quantmod). Let's just make a new, patched version called addOBV2 which is the code for addOBV except for the one patched line. (x <- as.matrix(lchob#xdata) is replaced with x <- try.xts(lchob#xdata, error=FALSE)).
addOBV2 <- function (..., on = NA, legend = "auto")
{
stopifnot("package:TTR" %in% search() || require("TTR", quietly = TRUE))
lchob <- quantmod:::get.current.chob()
x <- try.xts(lchob#xdata, error=FALSE)
#x <- as.matrix(lchob#xdata)
x <- OBV(price = Cl(x), volume = Vo(x))
yrange <- NULL
chobTA <- new("chobTA")
if (NCOL(x) == 1) {
chobTA#TA.values <- x[lchob#xsubset]
}
else chobTA#TA.values <- x[lchob#xsubset, ]
chobTA#name <- "chartTA"
if (any(is.na(on))) {
chobTA#new <- TRUE
}
else {
chobTA#new <- FALSE
chobTA#on <- on
}
chobTA#call <- match.call()
legend.name <- gsub("^.*[(]", " On Balance Volume (", deparse(match.call()))#,
#extended = TRUE)
gpars <- c(list(...), list(col=4))[unique(names(c(list(col=4), list(...))))]
chobTA#params <- list(xrange = lchob#xrange, yrange = yrange,
colors = lchob#colors, color.vol = lchob#color.vol, multi.col = lchob#multi.col,
spacing = lchob#spacing, width = lchob#width, bp = lchob#bp,
x.labels = lchob#x.labels, time.scale = lchob#time.scale,
isLogical = is.logical(x), legend = legend, legend.name = legend.name,
pars = list(gpars))
if (is.null(sys.call(-1))) {
TA <- lchob#passed.args$TA
lchob#passed.args$TA <- c(TA, chobTA)
lchob#windows <- lchob#windows + ifelse(chobTA#new, 1,
0)
chartSeries.chob <- quantmod:::chartSeries.chob
do.call("chartSeries.chob", list(lchob))
invisible(chobTA)
}
else {
return(chobTA)
}
}
Now it works.
# reproduce your data
ydat <- getSymbols("ZEEL.NS", src="yahoo", from="2012-09-11",
to="2013-01-18", auto.assign=FALSE)
lineChart(ydat, TA=NULL, name=paste("ZEEL Technical Graph"))
plot(addSMA(10))
plot(addEMA(10))
plot(addRSI())
plot(addADX())
plot(addOBV2())

This code reproduces the error:
library(quantmod)
getSymbols("AAPL")
lineChart(AAPL, 'last 6 months')
addOBV()
Session Info:
sessionInfo()
R version 2.15.0 (2012-03-30)
Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] quantmod_0.3-17 TTR_0.21-1 xts_0.9-1 zoo_1.7-9 Defaults_1.1-1 rgeos_0.2-11
[7] sp_1.0-5 sos_1.3-5 brew_1.0-6
loaded via a namespace (and not attached):
[1] grid_2.15.0 lattice_0.20-6 tools_2.15.0
Googling around, the error seems to be related to the fact that addOBV converts the data into a matrix, which causes problems with TTR::OBV. A patch has been posted on RForge.

Related

Other plots disappear when DataExplorer::plot_str() called

I have been using R and RStudio with base and ggplot for a couple of years. Lately, it seems that when some plots are generated, other plots are lost/deleted.
In RStudio, I use the "Plots" pane/tab, and the blue left and right arrows to view the plots that have been created. By disappears, I mean a plot was created and visible here, but if I use the arrows, I can't see it anymore. It was there, and it is not there anymore, it has "disappeared".
After running the code below using "Source" button, which does 3 plots, I can only see 2 plots. If I step through the code using Command-Return, I see the 3 plots generated, but then the middle one gets lost.
After doing more testing, I see for this code it is the call to:
DataExplorer::plot_str(mtcars)
that is the problem. If I comment that line and use another plot from DataExplorer like:
DataExplorer::plot_intro(mtcars)
all the plots are available after the script is complete.
I believe everything is using the latest versions:
mac os - 11.5.2
R - R version 4.1.1 (2021-08-10)
RStudio - RStudio 2021.09.0+351
R libraries - have just updated all the r libraries
Here is a simple base case that seems to recreate the issue. In the example below I am using the DataExplorer library, but I get similar stuff happening in Keras.
Code
########################### Start Initialisation ########################################################################################
# Remove objects from environment
rm(list = ls())
# Clear the R studio console
cat("\014")
# Clear all plots in R studio
try(dev.off(dev.list()["RStudioGD"]),silent<-TRUE)
try(dev.off(),silent<-TRUE)
# Load packages, installing first if not already installed
if (!require(DataExplorer)) {
install.packages("DataExplorer")
library(DataExplorer)
}
##################################
# Use base plotting to plot iris, this works
base::plot(iris, main="iris 1")
# Use DataExplorer::plot_str() to plot mtcars, this works, but then disappears
data("mtcars")
# DataExplorer::plot_str(mtcars) # This causes the problem
DataExplorer::plot_intro(mtcars) # This works
# This plot appears, but seems to cause the one above "mtcars" to disappear
base::plot(iris, main="iris 2")
sessionInfo()
Output:
> # Clear all plots in R studio
> try(dev.off(dev.list()["RStudioGD"]),silent<-TRUE)
null device
1
> try(dev.off(),silent<-TRUE)
> # Load packages, installing first if not already installed
> if (!require(DataExplorer)) {
+ install.packages("DataExplorer")
+ library(DataExpl .... [TRUNCATED]
> ##################################
>
> # Use base plotting to plot iris, this works
> base::plot(iris, main="iris 1")
> # Use DataExplorer::plot_str() to plot mtcars, this works, but then disappears
> data("mtcars")
> DataExplorer::plot_str(mtcars)
> # This plot appears but seems to cause the one above "mtcars" to disappear
> base::plot(iris, main="iris 2")
> sessionInfo()
R version 4.1.1 (2021-08-10)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Big Sur 11.5.2
Matrix products: default
LAPACK: /Library/Frameworks/R.framework/Versions/4.1/Resources/lib/libRlapack.dylib
locale:
[1] en_AU.UTF-8/en_AU.UTF-8/en_AU.UTF-8/C/en_AU.UTF-8/en_AU.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] DataExplorer_0.8.2
loaded via a namespace (and not attached):
[1] pillar_1.6.3 compiler_4.1.1 tools_4.1.1 digest_0.6.28 jsonlite_1.7.2 evaluate_0.14 lifecycle_1.0.1 tibble_3.1.4 gtable_0.3.0 pkgconfig_2.0.3
[11] rlang_0.4.11 igraph_1.2.6 DBI_1.1.1 yaml_2.2.1 parallel_4.1.1 xfun_0.26 fastmap_1.1.0 gridExtra_2.3 dplyr_1.0.7 knitr_1.36
[21] generics_0.1.0 vctrs_0.3.8 htmlwidgets_1.5.4 grid_4.1.1 tidyselect_1.1.1 glue_1.4.2 data.table_1.14.2 R6_2.5.1 fansi_0.5.0 rmarkdown_2.11
[31] ggplot2_3.3.5 purrr_0.3.4 magrittr_2.0.1 scales_1.1.1 ellipsis_0.3.2 htmltools_0.5.2 networkD3_0.4 assertthat_0.2.1 colorspace_2.0-2 utf8_1.2.2
[41] munsell_0.5.0 crayon_1.4.1
I thought perhaps the issue was due to mixing different plotting libraries, but the code below which draws 6 plots, 3 using base:plot() and 3 using ggplot2::ggplot() works and generates 6 plots that I can navigate through in RStudio using the blue left and right arrow buttons on the "Plots" pane/tab.
base::plot(mpg, main="mpg 1 - base")
ggplot2::ggplot(mpg, aes(displ, hwy, colour = class)) +
geom_point() +
ggtitle("mpg 1 - ggplot2")
base::plot(ToothGrowth, main="ToothGrowth 2 - base")
ggplot2::ggplot(ToothGrowth, aes(x=supp, y=len, fill=dose))+
geom_boxplot() +
ggtitle("ToothGrowth 2 - ggplot2")
base::plot(iris, main="iris 3 - base")
ggplot2::ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width, fill=Species))+
geom_boxplot() +
ggtitle("iris 3 - ggplot2")
RStudio is:
RStudio 2021.09.0+351 "Ghost Orchid" Release (077589bcad3467ae79f318afe8641a1899a51606, 2021-09-20) for macOS
Mozilla/5.0 (Macintosh; Intel Mac OS X 11_5_2) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.12.10 Chrome/69.0.3497.128 Safari/537.36
Mac os version:
(base) % uname -a
Darwin xxxx.lan 20.6.0 Darwin Kernel Version 20.6.0: Wed Jun 23 00:26:31 PDT 2021; root:xnu-7195.141.2~5/RELEASE_X86_64 x86_64
(base) % sw_vers
ProductName: macOS
ProductVersion: 11.5.2
BuildVersion: 20G95
I think the reason is a simple one: you're not outputting a real plot (static).
DataExplorer::plot_intro(mtcars) is the problematic "plot" and the underlying code for this includes diagonalNetwork towards the end of the function:
DataExplorer
function (data, type = c("diagonal", "radial"), max_level = NULL,
print_network = TRUE, ...)
{
i <- idx <- parent <- NULL
str_output_raw <- capture.output(str(data, vec.len = 0, give.attr = FALSE,
give.length = FALSE, list.len = 2000000000L))
str_output <- unlist(lapply(str_output_raw, function(x) {
gsub(" \\.{2}\\#", "\\$\\#", x)
}))
n <- length(str_output)
base_split <- tstrsplit(str_output[2:n], "\\$")
nest_level <- (nchar(base_split[[1]]) - nchar(gsub(" \\.{2}",
"", base_split[[1]])))/3 + 1
diff_nl <- diff(nest_level)
s4_start_index <- which(diff_nl > 1L) + 1L
if (length(s4_start_index) > 0) {
s4_end_index <- which(diff_nl == -2L)
s4_index_range <- unique(unlist(lapply(s4_start_index,
function(i) {
seq.int(i, s4_end_index[which.min(abs(s4_end_index -
i))])
})))
nest_level[s4_index_range] <- nest_level[s4_index_range] -
1L
}
if (is.null(max_level)) {
max_level <- max(nest_level)
}
else if (max_level <= 0 | max_level > max(nest_level)) {
stop(paste0("max_level should be between 1 and ",
max(nest_level)))
}
else {
max_level <- max_level
}
comp_split <- tstrsplit(base_split[[2]], ":")
comp_root <- gsub(" ", "", comp_split[[1]])
comp_root[which(comp_root == "")] <- make.names(comp_root[which(comp_root ==
"")], unique = TRUE)
if (anyDuplicated(comp_root))
comp_root[which(duplicated(comp_root))] <- make.names(comp_root[which(duplicated(comp_root))],
unique = TRUE)
comp_output <- paste0(comp_root, " (", trimws(gsub("NULL|\\.{3}|\\.{2}",
"", comp_split[[2]])), ")")
str_dt <- data.table(idx = seq_along(nest_level), nest_level,
parent = comp_output)[nest_level <= max_level]
str_dt <- str_dt[str_dt[, list(i = idx, nest_level = nest_level -
1, child = parent)], on = list(nest_level, idx < i),
mult = "last"]
drop_columns(str_dt[is.na(parent), `:=`(parent, paste0("root (",
str_output[1], ")"))], c("idx", "nest_level"))
str_to_list <- function(str_dt, root_name = as.character(str_dt[["parent"]][1])) {
str_list <- list(name = root_name)
children <- str_dt[parent == root_name][["child"]]
if (length(children) > 0) {
str_list[["children"]] <- lapply(children,
str_to_list, str_dt = str_dt)
}
str_list
}
str_list <- str_to_list(str_dt)
if (print_network) {
type <- match.arg(type)
if (type == "diagonal")
print(diagonalNetwork(str_list, ...))
if (type == "radial")
print(radialNetwork(str_list, ...))
}
invisible(str_list)
}
where diagonalNetwork uses htmlwidgets:
function (List, height = NULL, width = NULL, fontSize = 10, fontFamily = "serif",
linkColour = "#ccc", nodeColour = "#fff", nodeStroke = "steelblue",
textColour = "#111", opacity = 0.9, margin = NULL)
{
if (!is.list(List))
stop("List must be a list object.")
root <- List
margin <- margin_handler(margin)
options = list(height = height, width = width, fontSize = fontSize,
fontFamily = fontFamily, linkColour = linkColour, nodeColour = nodeColour,
nodeStroke = nodeStroke, textColour = textColour, margin = margin,
opacity = opacity)
htmlwidgets::createWidget(name = "diagonalNetwork",
x = list(root = root, options = options), width = width,
height = height, htmlwidgets::sizingPolicy(padding = 10,
browser.fill = TRUE), package = "networkD3")
}
htmlwidgets is an interactive "plot" and opens under RStudio's viewer pane and not the static plots pane.

Obtaining an error when running exact code from a blog

I am following a tutorial here. A few days ago I was able to run this code without error and run it on my own data set (it was always a little hit and miss with obtaining this error) - however now I try to run the code and I always obtain the same error.
Error in solve.QP(Dmat, dvec, Amat, bvec = b0, meq = 2) :
constraints are inconsistent, no solution!
I get that the solver cannot solve the equations but I am a little confused as to why it worked previously and now it does not... The author of the article has this code working...
library(tseries)
library(data.table)
link <- "https://raw.githubusercontent.com/DavZim/Efficient_Frontier/master/data/mult_assets.csv"
df <- data.table(read.csv(link))
df_table <- melt(df)[, .(er = mean(value),
sd = sd(value)), by = variable]
er_vals <- seq(from = min(df_table$er), to = max(df_table$er), length.out = 1000)
# find an optimal portfolio for each possible possible expected return
# (note that the values are explicitly set between the minimum and maximum of the expected returns per asset)
sd_vals <- sapply(er_vals, function(er) {
op <- portfolio.optim(as.matrix(df), er)
return(op$ps)
})
SessionInfo:
R version 3.5.3 (2019-03-11)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)
Matrix products: default
locale:
[1] LC_COLLATE=Spanish_Spain.1252 LC_CTYPE=Spanish_Spain.1252 LC_MONETARY=Spanish_Spain.1252
[4] LC_NUMERIC=C LC_TIME=Spanish_Spain.1252
attached base packages:
[1] parallel stats graphics grDevices utils datasets methods base
other attached packages:
[1] lpSolve_5.6.13.1 data.table_1.12.0 tseries_0.10-46 rugarch_1.4-0
loaded via a namespace (and not attached):
[1] Rcpp_1.0.0 MASS_7.3-51.1 mclust_5.4.2
[4] lattice_0.20-38 quadprog_1.5-5 Rsolnp_1.16
[7] TTR_0.23-4 tools_3.5.3 xts_0.11-2
[10] SkewHyperbolic_0.4-0 GeneralizedHyperbolic_0.8-4 quantmod_0.4-13.1
[13] spd_2.0-1 grid_3.5.3 KernSmooth_2.23-15
[16] yaml_2.2.0 numDeriv_2016.8-1 Matrix_1.2-15
[19] nloptr_1.2.1 DistributionUtils_0.6-0 ks_1.11.3
[22] curl_3.3 compiler_3.5.3 expm_0.999-3
[25] truncnorm_1.0-8 mvtnorm_1.0-8 zoo_1.8-4
tseries::portfolio.optim disallows short selling by default, see argument short. If short = FALSE asset weights may not go below 0. And as the weights must sum up to 1, also no individual asset weight could be above 1. There's no leverage.
(Possibly, in an earlier version of tseries default could have been short = TRUE. This would explain why it previously worked for you.)
Your target return (pm) cannot exceed the highest return of any of the input assets.
Solution 1: Allow short selling, but remember that that's a different efficient frontier. (For reference, see any lecture or book discussing Markowitz optimization. There's a mathematical solution to the problem without short-selling restriction.)
op <- portfolio.optim(as.matrix(df), er, shorts = T)
Solution 2: Limit the target returns between the worst and the best asset's return.
er_vals <- seq(from = min(colMeans(df)), to = max(colMeans(df)), length.out = 1000)
Here's a plot of the obtained efficient frontiers.
Here's the full script that gives both solutions.
library(tseries)
library(data.table)
link <- "https://raw.githubusercontent.com/DavZim/Efficient_Frontier/master/data/mult_assets.csv"
df <- data.table(read.csv(link))
df_table <- melt(df)[, .(er = mean(value),
sd = sd(value)), by = variable]
# er_vals <- seq(from = min(df_table$er), to = max(df_table$er), length.out = 1000)
er_vals1 <- seq(from = 0, to = 0.15, length.out = 1000)
er_vals2 <- seq(from = min(colMeans(df)), to = max(colMeans(df)), length.out = 1000)
# find an optimal portfolio for each possible possible expected return
# (note that the values are explicitly set between the minimum and maximum of the expected returns per asset)
sd_vals1 <- sapply(er_vals1, function(er) {
op <- portfolio.optim(as.matrix(df), er, short = T)
return(op$ps)
})
sd_vals2 <- sapply(er_vals2, function(er) {
op <- portfolio.optim(as.matrix(df), er, short = F)
return(op$ps)
})
plot(x = sd_vals1, y = er_vals1, type = "l", col = "red",
xlab = "sd", ylab = "er",
main = "red: allowing short-selling;\nblue: disallowing short-selling")
lines(x = sd_vals2, y = er_vals2, type = "l", col = "blue")

Error in grid.Call(L_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : polygon edge not found (new)

I know that the title of this question is a duplicate of this Question and this Question but the solutions over there don't work for me and the error message is (slightly) different:
Error in grid.Call(L_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
polygon edge not found
(note the missing part about the missing font)
I tried all suggestions that I found (updating / reinstalling all loaded graphic packages, ggplot2, GGally, and scales, reinitialising the Fonts on Mac OSX by starting in safe mode, moving the Fonts from /Fonts/ (Disabled) back into /Fonts...) but none of it resolved the problem.
The error seems to occure when I plot a ggplot graph with
scale_y_continuous(label=scientific_10)
where scientific_10 is defined as
scientific_10 <- function(x) {
parse(text = gsub("e", " %*% 10^", scientific_format()(x)))
}
Therefore the I suspect that the scales library has something to do with it.
The most puzzling is that the error only occurs each so-and-so many times, maybe each 3rd or 5th time i try to plot the same graph...
> sessionInfo()
R version 3.2.2 (2015-08-14)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: OS X 10.9.5 (Mavericks)
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] gridExtra_2.0.0 scales_0.3.0 broom_0.4.0 tidyr_0.3.1 ggplot2_1.0.1 GGally_0.5.0 dplyr_0.4.3
loaded via a namespace (and not attached):
[1] Rcpp_0.11.5 magrittr_1.5 MASS_7.3-43 mnormt_1.5-1 munsell_0.4.2 colorspace_1.2-6 lattice_0.20-33 R6_2.0.1
[9] stringr_0.6.2 plyr_1.8.1 tools_3.2.2 parallel_3.2.2 grid_3.2.2 gtable_0.1.2 nlme_3.1-121 psych_1.5.8
[17] DBI_0.3.1 htmltools_0.2.6 lazyeval_0.1.10 yaml_2.1.13 assertthat_0.1 digest_0.6.8 reshape2_1.4.1 rmarkdown_0.8.1
[25] labeling_0.3 reshape_0.8.5 proto_0.3-10
traceback()
35: grid.Call(L_textBounds, as.graphicsAnnot(x$label), x$x, x$y,
resolveHJust(x$just, x$hjust), resolveVJust(x$just, x$vjust),
x$rot, 0)
34: widthDetails.text(x)
33: widthDetails(x)
32: (function (x)
{
widthDetails(x)
})(list(label = expression(5 %*% 10^+5, 7.5 %*% 10^+5, 1 %*%
10^+6, 1.25 %*% 10^+6, 1.5 %*% 10^+6), x = 1, y = c(0.0777214770341215,
0.291044141334423, 0.504366805634725, 0.717689469935027, 0.931012134235329
), just = "centre", hjust = 1, vjust = 0.5, rot = 0, check.overlap = FALSE,
name = "axis.text.y.text.8056", gp = list(fontsize = 9.6,
col = "black", fontfamily = "", lineheight = 0.9, font = 1L),
vp = NULL))
31: grid.Call.graphics(L_setviewport, vp, TRUE)
30: push.vp.viewport(X[[i]], ...)
I solved it by installing the library extrafont, installing a set of specific fonts and forcing ggplot to use only these fonts:
require(extrafont)
# need only do this once!
font_import(pattern="[A/a]rial", prompt=FALSE)
require(ggplot2)
# extending the help file example
df <- data.frame(gp = factor(rep(letters[1:3], each = 10)), y = rnorm(30))
ds <- plyr::ddply(df, "gp", plyr::summarise, mean = mean(y), sd = sd(y))
plotobj <- ggplot(df, aes(gp, y)) +
geom_point() +
geom_point(data = ds, aes(y = mean), colour = 'red', size = 3) +
theme(text=element_text(size=16, family="Arial"))
print(plotobj)
I experienced the same issue when trying to plot ggplot/grid output to the graph window in Rstudio. However, plotting to an external graphing device seems to work fine.
The external device of choice depends on your system, but the script below, paraphrased from this blog, works for most systems:
a = switch(tolower(Sys.info()["sysname"]),
"darwin" = "quartz",
"linux" = "x11",
"windows" = "windows")
options("device" = a)
graphics.off()
rm(a)
and to switch back to using the Rstudio plot window:
options("device"="RStudioGD")
graphics.off()
Note that by switching, you lose any existing plots.
A lot of solutions for this particular error direct you to look under the hood of your computer but this error can also be caused by a scripting error in which R expects to match elements from two data structures but cannot.
For me the error was caused by calling a fairly complex graphing function (see below) that read an ordered character vector as well as a matrix whose row names were supposed to each match a value in the ordered character vector. The problem was that some of my values contained dashes in them and R's read.table() function translated those dashes to periods (Ex: "HLA-DOA" became "HLA.DOA").
I was using the ComplexHeatmap package with a call like this:
oncoPrint(mat,
get_type = function(x) strsplit(x, ";")[[1]],
alter_fun_list = alter_fun_list,
col = col,
row_order = my_order,
column_title = "OncoPrint",
heatmap_legend_param = list(title = "Alternations", at = c("AMP", "HOMDEL", "MUT"), labels = c("Amplification", "Deep deletion", "Mutation"))
)
In this call:
mat was a matrix that had dashes swapped out for periods
my_order was a character vector containing the same values as the row names of matexcept the dashes remained
every other argument is essential to the call but irrelevant to this post
To help R find this elusive "polygon edge", I just edited my character vector with:
row_order <- gsub("\\.", "-", row_order)
If you've tried re-installing packages, restarting your computer and re-enabling fonts - maybe check and see if you've got some faulty character matching going on in your call.
i tried to set the font of aes,returned the error info
the added words:
p <- p + theme(text = element_text(family = "宋体"))
when i tried to remove the setting,it's ok then.
Actually, I have the same problem on my MAC and couldn't solve it on a regular base... Since it also happens like every 5th or 10th execution I decided to wrap the whole ggplot command into a trycatch call and execute it until it doesn't fail...
The code would looks like this
error_appeared <- FALSE
repeat{
tryCatch({ # we put everything into a try catch block, because sometimes we get an error
gscat <-
ggplot() # my ggplot command which sometimes fail
ggsave('file.pdf', gscat, width=8,height=8)
plot(gscat)
},
error=function(e) {
print('redo the ratioscatterplot.')
error_appeared <- TRUE
}
)
if(!error_appeared){
break
}
}
Actually I figured out, only the drawing/plotting of the figure gives problems! Saving always works.
Maybe this is helping someone, since I couldn't find a solution which actually solves the whole thing!
Additional:
If somebody wants to play with the problem on a "reproducible example" the code below throws an average of 2 errors out of 20 within the loop.
library(scales)
library(ggplot2)
df <- data.frame(
log2.Ratio.H.L.normalized.rev = c(2.53861265542646, 0.402176424979483, 0.438931541934545, 0.639695233399582, 0.230203013366421,
2.88223218956399, 1.23051046036618, 2.56554843533357, 0.265436896049098,
1.32866415755805, -0.92108963514092, 0.0976107966264223, -0.43048946484291,
-0.558665259531966, 4.13183638727079, 0.904580434921318, -0.0733780789564803,
-0.621932351219966, 1.48594198341242, -0.365611185917855, 1.21088754922081,
-2.3717583289898, 2.95160644380282, 3.71446534016249),
Intensity = c(5951600000, 2.4433e+10, 1.1659e+10, 2273600000, 6.852e+10, 9.8746e+10, 5701600000,
1758500000, 987180000, 3.4167e+11, 1.5718e+10, 6.8888e+10, 5.5936e+10,
8702900000, 1093500000, 4426200000, 1.3681e+11, 7.773e+09, 5860400000,
1.2861e+12, 2017900000, 2061300000, 240520000, 1382700000),
my_label = c("RPL18",
"hCG_2024613", "NOL7", "PRPF4B", "HIST1H2BC", "XRCC1", "C9orf30",
"CABIN1", "MGC3731", "XRCC6", "RPL23", "RPL27", "RPL17", "RPL32",
"XPC", "RPL15", "GNL3", "RPL29", "JOSD3", "PARP1", "DNAPTP6",
"ORC2L", "NCL", "TARDBP"))
unlink("figures", recursive=TRUE)
if(!dir.exists('figures')) dir.create('figures')
for(i in 1:20) {
error_appeared <- FALSE
repeat{
tryCatch({ # we put everything into a try catch block, because sometimes we get an error
gscat <-
ggplot(df, aes_string("log2.Ratio.H.L.normalized.rev", 'Intensity')) +
geom_point(data=df[abs(df[["log2.Ratio.H.L.normalized.rev"]]) < 1,],
color='black', alpha=.3, na.rm=TRUE) +
scale_y_log10(labels = scales::trans_format("log10", scales::math_format()))
ggsave(file.path('figures', paste0('intensity_scatter_', i, '.pdf')),
gscat, width=8, height=8)
plot(gscat)
},
error=function(e) {
# print(e)
print(sprintf('%s redo the ratioscatterplot.', i))
error_appeared <- TRUE
}
)
if(!error_appeared){
break
}
}
}

using ggsave and arrangeGrob after updating gridExtra to 2.0.0

since I read a lot similar question on stackoverflow so far, I couldn't find a good solution without updating ggplot2 to the development version.
My problem, I have several scripts which use arrangeGrob to create combined graph out of individual graphs. I save them into a variable and print this variable and/or save it with ggsave. Since a lot of my colleagues update there packages regularly (which is a good thing I think), I always get mails my script no longer work after updating to gridExtra 2.0.0.
I am not sure how to handle this, since the new ggplot2 version where the problem is solved is still under development. I found an article on stack overflow to remove a test if the object to save is a ggplot since the new arrangeGrob function returns a gtable object, but this fails in my case:
library(ggplot2)
library(grid)
library(gridExtra)
a <- data.frame(x=c(1,2,3),
y=c(2,3,4))
p <- ggplot(a, aes(x, y)) + geom_point()
b <- arrangeGrob(p, p)
grid.draw(b)
ggsave('test.pdf', b)
ggsave <- ggplot2::ggsave
body(ggsave) <- body(ggplot2::ggsave)[-2]
ggsave('test.pdf', b)
Some output and error on the console:
d> grid.draw(b)
d> ggsave('test.pdf', b)
Error in ggsave("test.pdf", b) : plot should be a ggplot2 plot
d> ggsave <- ggplot2::ggsave
d> body(ggsave) <- body(ggplot2::ggsave)[-2]
d> ggsave('test.pdf', b)
Saving 10.5 x 10.7 in image
TableGrob (2 x 1) "arrange": 2 grobs
z cells name grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (2-2,1-1) arrange gtable[layout]
d>
The test.pdf is created but it is corrupted in any way and can not be opened. Also the gtable object get printed. So I guess something is wrong here.
But, as you can see, I found in the example code, I found the grid.draw function to plot at least my combined graph but I still can not ggsave it after the modification.
I don't want to use the "old" (pdf(file = "test.pdf"); grid.draw(b); dev.off()) device saving functions as suggested in this article, since they are very uncomfortable to use.
In this question someone asked exactly how to save the object, but in the answer they just explain to use grid.darw and he accepted the answer as solving the problem and nobody answered on my comments so far.
So I am pretty lost at the moment, how to provide working scripts for those who have and have not updated to new gridExtra package. The way to remove the test within the ggsave function is I guess the best solution since I can check the gridExtra and ggplot2 version and just overwrite the ggsave function in case there version do not match, but I could not get it to run.
Looking forward to get some help.
EDIT:
maybe the sessionInfo helps
d> sessionInfo()
R version 3.2.0 (2015-04-16)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: OS X 10.9.5 (Mavericks)
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] grid stats graphics grDevices utils datasets methods base
other attached packages:
[1] gridExtra_2.0.0 ggplot2_1.0.1
loaded via a namespace (and not attached):
[1] Rcpp_0.12.1 digest_0.6.8 MASS_7.3-44 plyr_1.8.3 gtable_0.1.2
[6] magrittr_1.5 scales_0.3.0 stringi_1.0-1 reshape2_1.4.1 devtools_1.9.1
[11] proto_0.3-10 tools_3.2.0 stringr_1.0.0 munsell_0.4.2 colorspace_1.2-6
[16] memoise_0.2.1
As an temporary workaround for this unfortunate transition period, you could re-implement the class hack that used to be in gridExtra,
class(b) <- c("arrange","ggplot", class(b))
print.arrange <- function(x) grid.draw(x)
ggsave('test.pdf', b)
Pascal brought me finally to the idea to check for the differences between ggplot 1.0.1 and ggplot 1.0.1.9003, since I don't want to or force the development version of ggplot.
So my idea is a function which will be executed within each script which overwrites the default ggsave function.
I tested it now a little, if there are any bugs or so, please let me know. But the way I do it now it works so far.
repairGgsave <- function() {
ggplot_version <-
compareVersion(as.character(packageVersion('ggplot2')),
'1.0.1.9003')
gridextra_version <-
compareVersion(as.character(packageVersion('gridExtra')),
'0.9.1')
if(gridextra_version > 0) {
if(ggplot_version <= 0) {
ggsave <- function(filename, plot = last_plot(),
device = NULL, path = NULL, scale = 1,
width = NA, height = NA, units = c("in", "cm", "mm"),
dpi = 300, limitsize = TRUE, ...) {
dev <- plot_dev(device, filename, dpi = dpi)
dim <- plot_dim(c(width, height), scale = scale, units = units,
limitsize = limitsize)
if (!is.null(path)) {
filename <- file.path(path, filename)
}
dev(file = filename, width = dim[1], height = dim[2], ...)
on.exit(utils::capture.output(grDevices::dev.off()))
grid.draw(plot)
invisible()
}
assign("ggsave", ggsave, .GlobalEnv)
plot_dim <<- function(dim = c(NA, NA), scale = 1, units = c("in", "cm", "mm"),
limitsize = TRUE) {
units <- match.arg(units)
to_inches <- function(x) x / c(`in` = 1, cm = 2.54, mm = 2.54 * 10)[units]
from_inches <- function(x) x * c(`in` = 1, cm = 2.54, mm = 2.54 * 10)[units]
dim <- to_inches(dim) * scale
if (any(is.na(dim))) {
if (length(grDevices::dev.list()) == 0) {
default_dim <- c(7, 7)
} else {
default_dim <- dev.size() * scale
}
dim[is.na(dim)] <- default_dim[is.na(dim)]
dim_f <- prettyNum(from_inches(dim), digits = 3)
message("Saving ", dim_f[1], " x ", dim_f[2], " ", units, " image")
}
if (limitsize && any(dim >= 50)) {
stop("Dimensions exceed 50 inches (height and width are specified in '",
units, "' not pixels). If you're sure you a plot that big, use ",
"`limitsize = FALSE`.", call. = FALSE)
}
dim
}
plot_dev <<- function(device, filename, dpi = 300) {
if (is.function(device))
return(device)
eps <- function(...) {
grDevices::postscript(..., onefile = FALSE, horizontal = FALSE,
paper = "special")
}
devices <- list(
eps = eps,
ps = eps,
tex = function(...) grDevices::pictex(...),
pdf = function(..., version = "1.4") grDevices::pdf(..., version = version),
svg = function(...) grDevices::svg(...),
emf = function(...) grDevices::win.metafile(...),
wmf = function(...) grDevices::win.metafile(...),
png = function(...) grDevices::png(..., res = dpi, units = "in"),
jpg = function(...) grDevices::jpeg(..., res = dpi, units = "in"),
jpeg = function(...) grDevices::jpeg(..., res = dpi, units = "in"),
bmp = function(...) grDevices::bmp(..., res = dpi, units = "in"),
tiff = function(...) grDevices::tiff(..., res = dpi, units = "in")
)
if (is.null(device)) {
device <- tolower(tools::file_ext(filename))
}
if (!is.character(device) || length(device) != 1) {
stop("`device` must be NULL, a string or a function.", call. = FALSE)
}
dev <<- devices[[device]]
if (is.null(dev)) {
stop("Unknown graphics device '", device, "'", call. = FALSE)
}
dev
}
}
}
}
It basically overwrites the ggsave and creates two new functions from the development version.
After executing the function everything seems to work.
Fix for me was explicitly defining the file:
ggsave(file='test.pdf', b)

Missing object error when using step() within a user-defined function

5 days and still no answer
As can be seen by Simon's comment, this is a reproducible and very strange issue. It seems that the issue only arises when a stepwise regression with very high predictive power is wrapped in a function.
I have been struggling with this for a while and any help would be much appreciated. I am trying to write a function that runs several stepwise regressions and outputs all of them to a list. However, R is having trouble reading the dataset that I specify in my function arguments. I found several similar errors on various boards (here, here, and here), however none of them seemed to ever get resolved. It all comes down to some weird issues with calling step() in a user-defined function. I am using the following script to test my code. Run the whole thing several times until an error arises (trust me, it will):
test.df <- data.frame(a = sample(0:1, 100, rep = T),
b = as.factor(sample(0:5, 100, rep = T)),
c = runif(100, 0, 100),
d = rnorm(100, 50, 50))
test.df$b[10:100] <- test.df$a[10:100] #making sure that at least one of the variables has some predictive power
stepModel <- function(modeling.formula, dataset, outfile = NULL) {
if (is.null(outfile) == FALSE){
sink(file = outfile,
append = TRUE, type = "output")
print("")
print("Models run at:")
print(Sys.time())
}
model.initial <- glm(modeling.formula,
family = binomial,
data = dataset)
model.stepwise1 <- step(model.initial, direction = "backward")
model.stepwise2 <- step(model.stepwise1, scope = ~.^2)
output <- list(modInitial = model.initial, modStep1 = model.stepwise1, modStep2 = model.stepwise2)
sink()
return(output)
}
blah <- stepModel(a~., dataset = test.df)
This returns the following error message (if the error does not show up right away, keep re-running the test.df script as well as the call for stepModel(), it will show up eventually):
Error in is.data.frame(data) : object 'dataset' not found
I have determined that everything runs fine up until model.stepwise2 starts to get built. Somehow, the temporary object 'dataset' works just fine for the first stepwise regression, but fails to be recognized by the second. I found this by commenting out part of the function as can be seen below. This code will run fine, proving that the object 'dataset' was originally being recognized:
stepModel1 <- function(modeling.formula, dataset, outfile = NULL) {
if (is.null(outfile) == FALSE){
sink(file = outfile,
append = TRUE, type = "output")
print("")
print("Models run at:")
print(Sys.time())
}
model.initial <- glm(modeling.formula,
family = binomial,
data = dataset)
model.stepwise1 <- step(model.initial, direction = "backward")
# model.stepwise2 <- step(model.stepwise1, scope = ~.^2)
# sink()
# output <- list(modInitial = model.initial, modStep1 = model.stepwise1, modStep2 = model.stepwise2)
return(model.stepwise1)
}
blah1 <- stepModel1(a~., dataset = test.df)
EDIT - before anyone asks, all the summary() functions were there because the full function (i edited it so that you could focus in on the error) has another piece that defines a file to which you can output stepwise trace. I just got rid of them
EDIT 2 - session info
sessionInfo()
R version 2.15.1 (2012-06-22)
Platform: x86_64-pc-mingw32/x64 (64-bit)
locale:
[1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252 LC_NUMERIC=C
[5] LC_TIME=English_United States.1252
attached base packages:
[1] tcltk stats graphics grDevices utils datasets methods base
other attached packages:
[1] sqldf_0.4-6.4 RSQLite.extfuns_0.0.1 RSQLite_0.11.3 chron_2.3-43
[5] gsubfn_0.6-5 proto_0.3-10 DBI_0.2-6 ggplot2_0.9.3.1
[9] caret_5.15-61 reshape2_1.2.2 lattice_0.20-6 foreach_1.4.0
[13] cluster_1.14.2 plyr_1.8
loaded via a namespace (and not attached):
[1] codetools_0.2-8 colorspace_1.2-1 dichromat_2.0-0 digest_0.6.2 grid_2.15.1
[6] gtable_0.1.2 iterators_1.0.6 labeling_0.1 MASS_7.3-18 munsell_0.4
[11] RColorBrewer_1.0-5 scales_0.2.3 stringr_0.6.2 tools_2.15
EDIT 3 - this performs all the same operations as the function, just without using a function. This will run fine every time, even when the algorithm doesn't converge:
modeling.formula <- a~.
dataset <- test.df
outfile <- NULL
if (is.null(outfile) == FALSE){
sink(file = outfile,
append = TRUE, type = "output")
print("")
print("Models run at:")
print(Sys.time())
}
model.initial <- glm(modeling.formula,
family = binomial,
data = dataset)
model.stepwise1 <- step(model.initial, direction = "backward")
model.stepwise2 <- step(model.stepwise1, scope = ~.^2)
output <- list(modInitial = model.initial, modStep1 = model.stepwise1, modStep2 = model.stepwise2)
Using do.call to refer to the data set in the calling environment works for me. See https://stackoverflow.com/a/7668846/210673 for the original suggestion. Here's a version that works (with sink code removed).
stepModel2 <- function(modeling.formula, dataset) {
model.initial <- do.call("glm", list(modeling.formula,
family = "binomial",
data = as.name(dataset)))
model.stepwise1 <- step(model.initial, direction = "backward")
model.stepwise2 <- step(model.stepwise1, scope = ~.^2)
list(modInitial = model.initial, modStep1 = model.stepwise1, modStep2 = model.stepwise2)
}
blah <- stepModel2(a~., dataset = "test.df")
It fails for me consistently with set.seed(6) with the original code. The reason it fails is that the dataset variable is not present within the step function, and although it's not needed in making model.stepwise1, it is needed for model.stepwise2 when model.stepwise1 keeps a linear term. So that's the case when your version fails. Calling the dataset from the global environment as I do here fixes this issue.

Resources