I want to add vertical lines on several dates on a certain graph. So far I haven't managed to achieve this simple task. This is what I tried:
> s <- get(getSymbols('nvmi'))["2012::"]
> d1 <- index(s[100])
> d1
[1] "2012-05-24"
> chart_Series(s,TA="addLines(v=d1)")
Error in get.current.chob() : improperly set or missing graphics device
> chart_Series(s)
> abline(v=d1)
# nothing
> add_TA("addLines(v=d1")
Error in `[.data.frame`(lenv$xdata, Env$xsubset) :
undefined columns selected
From what I have already read here, I know that abline is not supposed to work with the new chart_Series function. It doesn't seem to work anyway. The addLines function does not work in any of the forms I tried - plain addLines, plot(addLines(...)), chart_Series(..., TA="addLines(...)") or add_TA("addLines(...)").
I need to use the experimental version of quantmod because it solved other problems I had with the old version. d1 would eventually be a list of dates.
You can't mix functions from the old and new versions of quantmod's charting functions. If you want to use addLines, you have to use chartSeries. Even if you use addLines and chartSeries, d1 should be an xts object, not a datetime object. For example:
library(quantmod)
data(sample_matrix)
s <- as.xts(sample_matrix)
chartSeries(s,TA="addLines(v=s[100])")
If you want to add a vertical line using chart_Series, create a logical xts object with TRUE values where you want the lines to appear and FALSE otherwise. For example:
l <- xts(!as.logical(s[,1]),index(s))
l[100] <- TRUE
chart_Series(s,TA="add_TA(l,on=1)")
Also note that you can put the vertical line "behind" the chart by using on=-1 in the add_TA call:
chart_Series(s,TA="add_TA(l,on=-1,col='grey',border='grey')")
add horizontal line my example:
library(quantmod)
library(lubridate)
stockId<-"CVS"
showperiod<-6 # 6 months
stockData<-getSymbols(stockId, src="yahoo",auto.assign=FALSE)
startDate<-Sys.Date()-months(showperiod,abbreviate = FALSE)
fromDate<-paste0(year(startDate),month(startDate))
subset<-paste0(fromDate,"/")
mytheme <- chart_theme()
mytheme$col$dn.col <- "firebrick1"
mytheme$col$up.col <- "darkgreen"
chart_Series(stockData, name = stockId, subset = subset, theme = mytheme)
#if you add line at 2018-6-18 to 2018-07-16 & y(price)=72
#you need creat new data to plot
#
ntick<-nrow(stockData["20180618/20180716"]) #2018-6-18 to 2018-07-16 tick numbers
getDate<-index(stockData["20180618/20180716"])
y<-rep(72,ntick)
df<-data.frame(getDate,y)
linedata<-xts(df$y,order.by = df$getDate)
# add line
add_TA(linedata,on=-1,col="blue",lwd=2)
enter image description here
Related
I have a very simple timeline I've created using the vistime library in R:
library(vistime)
library(plotly)
data <- read.csv(text="event,group,start,end,color,line.color
RedBorder,Project,2016-12-22,2016-12-22,#e8a735,#FF0000
BlueBorder,Meetings,2012-03-15,2012-03-15,#e8a735,#0000ff
BlueBorder,Meetings,2017-01-12,2017-01-12,#e8a735,#0000ff
BlueBorder,Meetings,2019-09-12,2019-09-12,#e8a735,#0000ff
BlueBorder,Meetings,2018-08-15,2017-08-15,#e8a735,#0000ff
RedBorder,Meetings,2017-01-15,2017-01-15,#e8a735,#FF0000")
#Ordering the data, oldest to newest -- this sorts correctly
data <- data[order(data$start),]
p <- vistime(data)
pb <- plotly_build(p)
#The plot's dates are not ordered
pb$x$data[[2]]$x
#Attempting to order the plot's data. These are the date elements. No luck ordering.
pb[order(pb$x$data[[2]]$x)]
for (i in 1:length(pb$x$data)) {
if (pb$x$data[[i]]$mode == "markers") pb$x$data[[i]]$marker$line$color<- data$line.color
}
pb
I'm trying to get the line color to match what is in the line.color column, but as you see, it's not assigning the correct line color to the points. For example, RedBorder should have red outlines, and BlueBorder events should have blue outlines.
This was tricky! It seems you are getting burned by internal sorting of the data (based on time) inside the "built" Plotly object relative to your input data.
Basically, the data$line.color does not have the right sort order so the colors were not being mapped to the correct markers.
Simply pre-ordering your data based on Date e.g. order(data$start) fixes the problem. Moves data row 4 to position 3. EDIT: it appears that sort order may be more complicated, so use match to set the order of data after making pb
Final edit with more complex data:
I originally posted edits without your complete update. You need to know what index of pb$x$data contains your marker X-positions. In your first example it was index 2, in your new example it is index 4.
library(vistime)
library(plotly)
data <- read.csv(text="event,group,start,end,color,line.color
RedBorder,Project,2016-12-22,2016-12-22,#e8a735,#FF0000
BlueBorder,Meetings,2012-03-15,2012-03-15,#e8a735,#0000ff
BlueBorder,Meetings,2017-01-12,2017-01-12,#e8a735,#0000ff
BlueBorder,Meetings,2019-09-12,2019-09-12,#e8a735,#0000ff
BlueBorder,Meetings,2018-08-15,2017-08-15,#e8a735,#0000ff
RedBorder,Meetings,2017-01-15,2017-01-15,#e8a735,#FF0000")
data <- as.data.frame(data)
data$color <- rgb(1,1,1,0)
p <- vistime(data)
pb <- plotly_build(p)
for (i in 1:length(pb$x$data)) {
if (pb$x$data[[i]]$mode == "markers") {
data <- data[match(strftime(pb$x$data[[i]]$x, "%Y-%m-%d"), data$start),]
pb$x$data[[i]]$marker$line$color<- data$line.color
}
}
#> [1] 4
I am very new to R and would like to use some code to run various batch code on all of the data that I have available. It should be clear what I'm trying to do:
# library(PerformanceAnalytics)
# mydata <- mtcars[, c('mpg', 'cyl', 'disp', 'hp', 'carb')];
# chart.Correlation(mydata, histogram=TRUE, pch=19)
library(MASS)
M_names = data(package = "MASS")$result[, "Item"]
for (i in 1:length(M_names)) {
eval(paste("MASS::", M_names[i], sep=""));
}
The commented part is some code I found that I haven't been able to integrate yet. The Correlation is a very cool correlation matrix, which I'm attempting to funnel every single dataset I have access to into so I can quickly review them instead of doing it all manually. I guess I will need to save them all to PNGs to have practical workflow around that, as it's clear there's no way to coax the X windows to appear or stay put when running R code as a script.
The behavior I observe as I execute this on my Mac is:
> library(MASS)
> M_names = data(package = "MASS")$result[, "Item"]
> for (i in 1:length(M_names)) {
+ eval(paste("MASS::", M_names[i], sep=""));
+ }
>
>
I don't know for sure what the silent + indicator means, but I'm pretty sure it just means that code line is inside the for loop scope. But the eval is swallowing the command I assembled. I'm just trying to get it to print out the content of the data at each iteration of the loop for now.
I also noticed this:
> eval("MASS::ships")
[1] "MASS::ships"
It just prints it when I try to eval it.
I also hope there is a way to programmatically print individual datasets. I'm already hacking really hard at this, and there is no way that what I am doing here is a good idea.
If you have the package dataset names in a vector the key to accessing them
by their character names is the get function:
library(MASS)
M_names = data(package = "MASS")$result[, "Item"]
head(get(M_names[1]), 1)
# state sex diag death status T.categ age
# 1 NSW M 10905 11081 D hs 35
You can then loop through the vector of names
for (DATA in M_names) print(summary(get(DATA)))
Another options is to use the envir argument of the data function to load the datasets into a specific environment. It may be worth adding the data to a new environment instead of polluting your workspace.You can do that with
data(list=M_names, package="MASS", envir = list_of_datafames<- new.env())
You can then look through the list_of_datafames as you would with an other list object:
lapply(list_of_datafames, summary)
How can I create an image from a data frame? For example:
library(tidyverse)
library(gridExtra)
df = iris %>% slice(1:4)
I've the following but:
1. I haven't been able to get this to be saved to a variable. It just pops up in the plots pane of Rstudio. Am I missing something obvious? I'd like to be able to have this plot referenced to a variable so I could save it as a png or something.
2. Is there a way to remove the row numbers that seem to appear?
3. This look is fine, but is there a way to make it more of a lighter background compared to what this is?
gridExtra::grid.table(df)
To save a relevant variable, use
myTable <- tableGrob(df)
since
grid.table
# function (...)
# grid.draw(tableGrob(...))
# <bytecode: 0x10758c078>
# <environment: namespace:gridExtra>
Given that, you can run
library(grid)
grid.draw(myTable)
For that you want
myTable <- tableGrob(df, rows = NULL)
See ?tableGrob and particularly ttheme_default (its source code makes pretty clear what are possible parameters; see also here). For instance,
myTable <- tableGrob(
df,
rows = NULL,
theme = ttheme_default(core = list(bg_params = list(fill = "grey99")))
)
grid.draw(myTable)
I generate a bunch of graphs and write them into a list variable, something like the following.
graphsListHolder <- list()
loop around the following code for as many plots as I make
filename <- paste some elements together to create a unique name
graphsListHolder[[filename]] <- p # p is the name of the ggplot plot
I save graphsListHolder as a .rds file.
Later I want to read in the res file, choose from plots in the graphsListHolder file and display with grid.arrange. I can hardcode the plot number and the following example works fine when run, plotting two graphs, one on top of the other.
grid.arrange(
graphsListHolder[[3]], graphsListHolder[[5]]
)
But if I construct a character variable temp like this (or variations on this)
temp <- "graphsListHolder[[3]], graphsListHolder[[5]]"
and change the grid.arrange code to
grid.arrange(
temp
)
I get
Error in gList(list("graphsListHolder[[3]], graphsListHolder[[5]]", wrapvp = list( :
only 'grobs' allowed in "gList"
In addition: Warning message:
In grob$wrapvp <- vp : Coercing LHS to a list
I also tried eval(parse(text = temp) without success.
I'm not sure how you want to choose them, but say you had a vector of the elements you wanted
x <- c(3,5)
Then you could do
grid.arrange(grobs=graphsListHolder[x])
Trying to turn arbitrary strings into executable code usually isn't a good idea. Often there are more "traditional" alternatives in R.
For example
graphsListHolder<-Map(function(x) {
ggplot(data.frame(x=1:10, y=x*1:10)) + geom_point(aes(x,y)) + ggtitle(x)}, 1:5)
x <- c(3,5)
grid.arrange(grobs=graphsListHolder[x])
I've made a loop to create multiple boxplots. The thing is, I want to save all the boxplots without overwriting each other. Any suggestions?
This is my current code:
boxplot <- list()
for (x in 1:nrow(checkresults)){
boxplots <- boxplot(PIM[,x], MYC [,x], OBX[,x], WDR[,x], EV[,x],
main=colnames(PIM)[x],
xlab="PIM, MYC, OBX, WDR, EV")
}
Do you want to save them in some files, or save them to be able to look at them in different windows ?
If it is the first case, you can use a png, pdf or whatever function call inside your for loop :
R> for (i in 1:5) {
R> png(file=paste("plot",i,".png",sep=""))
R> plot(rnorm(10))
R> dev.off()
R> }
If you want to display them in separate windows, just use dev.new :
R> for (i in 1:5) {
R> dev.new()
R> plot(rnorm(10));
R> }
Just to add to #juba's answer, if you want to save the plots to a multi-page pdf file, then you don't have to use the paste command that #juba suggested. This
pdf("myboxplots.pdf")
for (x in seq_along(boxplots)){
boxplot(PIM[,x], MYC [,x], OBX[,x], WDR[,x],EV[,x],
main = colnames(PIM)[x],
xlab = "PIM, MYC, OBX, WDR, EV")
}
dev.off()
creates a single multi-page pdf document, where each page is a boxplot. If you want to store the boxplots in separate pdf documents, then use the file=paste command.
First, create a list of the right length - it just makes things easier and is good practice to allocate storage before filling objects in via a loop:
boxplots <- vector(mode = "list", length = nrow(checkresults))
Then we can loop over the data you want, assigning to each component of the boxplots list as we go, using the [[x]] notation:
for (x in seq_along(boxplots)){
boxplots[[x]] <- boxplot(PIM[,x], MYC [,x], OBX[,x], WDR[,x],EV[,x],
main = colnames(PIM)[x],
xlab = "PIM, MYC, OBX, WDR, EV")
}
Before, your code was overwriting the previous boxplot info during subsequent iterations.