Is it possible to change the legend on the plot displayed in Quantmod so that values are displayed rather than the variable name? For example:
library("quantmod")
getSymbols("YHOO")
temp1 <- 6
temp2 <- "SMA"
barChart(YHOO)
addTA(ADX(YHOO, n=temp1, maType=temp2))
The legend that is displayed in the plot is ADX(YHOO, n=temp1, maType=temp2). I would like it to display the specific values instead i.e. ADX(YHOO, n=6, maType='SMA').
There isn't a way to do this automatically with addTA, because it would need to know which of the the parameters of the TA call it needs to evaluate. But you can do it manually by setting the legend= argument yourself.
One way to do it is to use paste (or paste0).
barChart(YHOO)
Legend <- paste0('ADX(YHOO, n=',temp1,', maType=',temp2,')')
addTA(ADX(YHOO, n=temp1, maType=temp2), legend=Legend)
Or you could create and manipulate the call to get what you want.
barChart(YHOO)
callTA <- call("ADX",quote(YHOO),n=temp1,maType=temp2)
eval(call("addTA", callTA, legend=deparse(callTA)))
The following is a partial solution which displays the values rather than variable names in the legend as well as the relevant output values for the TA. However, unlike the default settings of addTA, the text for each output value doesn't match the colour of the line on the addTA plot. Unfortunately I haven't worked out how to get the text of the output values to match the colour of its relevant line on the addTA plot. Any suggestions?
library("quantmod")
getSymbols("YHOO")
barChart(YHOO, subset="last 4 months")
col <- c("red", "blue", "green", "orange")
temp1 <- 8
temp2 <- "SMA"
temp <- ADX(HLC(YHOO), n=temp1, maType=temp2)
legend <- rep(NA, NCOL(temp)+1)
legend[1] <- paste("ADX(HLC(YHOO)", "n=", temp1, "maType=", temp2)
for(x in 2:(NCOL(temp)+1)){
legend[x] <- (paste(colnames(temp[,(x-1)]),": ", round(last(temp[,(x-1)]),3), sep=""))
}
addTA(temp, legend = legend, col=col)
Related
I have data with the following columns: lot, sublot, size, data. I have multiple lot(s) and each lot can have multiple sublot(s). Each sublot has size(s) of 1 to 4.
I have created a boxplot for this data using the following code:
df <-
readXL("Z:/R_Files/example.xlsx",
rownames=FALSE, header=TRUE, na="", sheet="Sheet1",
stringsAsFactors=TRUE)
x11()
par(mar=c(10.1, 5.1, 4.1, 2.1))
boxplot(data ~ size*sublot*lot,
xlab="", ylab="Data", main="Data by Size, Sublot, Lot",
las=2,
data=df)
title(xlab='Size.Sublot.Lot', line=9)
I wanted to use the boxfill command to color each boxplot based on the lot#. I have seen two solutions:
create a vector and explicitly specify the colors to be used e.g. colr = c("red", "red", "red", .... "green", "green", "green", ... "blue"). The problem with this solution is that it requires me to know apriori the number of lots in df and number of times the color needs to be repeated.
use "ifelse" statement. The problem with this solution is that (a) I need to know the number of lots and (b) I need to create multiple nested ifelse statements.
I would prefer to create a "dynamic" solution which creates the color vector based on the number of lot entries I have in my file.
I have tried to create:
uniqlot <- unique(df$lot)
colr <- palette(rainbow(length(uniqlot)))
but am stuck since the entries in the colr vector do not repeat for the number of unique combinations of size.sublot.lot. Note: I want all boxplots for lot ABC to be colored with one color, all boxplots for lot DEF to be colored with another color etc.
I am attaching a picture of the uncolored boxplot. Uncolored Boxplot
Raw data (example.xlsx) can be accessed at the following link:
example.xlsx
This is what I would do:
n1 <- length(unique(df$sublot))
n2 <- length(unique(df$size))
colr <- palette(rainbow(length(n)))
colr <- rep(colr, each = n1*n2)
boxplot(data ~ size*sublot*lot,
col = colr,
xlab="", ylab="Data", main="Data by Size, Sublot, Lot",
las=2,
data=df)
Using ggplot:
df$size <- as.factor(df$size)
ggplot(df, aes(sublot, data, group = interaction(size, sublot), col = size)) +
geom_boxplot() +
facet_wrap(~lot, nrow = 1)
Also, you can get rid of df$size <- as.factor(df$size) if you want continuous colour.
thanks to the pointers provided in the responses and after digging around a little more, I was able to find a solution to my own question. I wanted to submit this piece of code in case someone needed to replicate.
Here is a picture of the boxplot this code creates (and I wanted to create). colored boxplot
df <-
readXL("Z:/R_Files/example.xlsx",
rownames=FALSE, header=TRUE, na="", sheet="Sheet1",
stringsAsFactors=TRUE)
unqlot <- unique(df$lot)
unqsublot <- unique(df$sublot)
unqsize <- unique(df$size)
cul <- palette(rainbow(length(unqlot)))
culur <- character()
for (i in 1:length(unqsize)) {
culur_temp = rep(cul[i], each=(length(unqsize)*length(unqsublot)))
culur = c(culur, culur_temp)
}
par(mar=c(10.1, 5.1, 4.1, 2.1))
boxplot(data ~ size*sublot*lot,
xlab="", ylab="Data", main="Data by Size, Sublot, Lot",
col = culur,
las=2,
data=df)
This is my code to create a boxplot in R that has 4 boxplots in one.
psnr_x265_256 <- c(39.998,39.998, 40.766, 38.507,38.224,40.666,38.329,40.218,44.746,38.222)
psnr_x264_256 <- c(39.653, 38.106,37.794,36.13,36.808,41.991,36.718,39.26,46.071,36.677)
psnr_xvid_256 <- c(33.04564,33.207269,32.715427,32.104696,30.445141,33.135261,32.669766, 31.657039,31.53103,31.585865)
psnr_mpeg2_256 <- c(32.4198,32.055051,31.424819,30.560274,30.740421,32.484694, 32.512268,32.04659,32.345848, 31)
all_errors = cbind(psnr_x265_256, psnr_x264_256, psnr_xvid_256,psnr_mpeg2_256)
modes = cbind(rep("PSNR",10))
journal_linear_data <-data.frame(psnr_x265_256, psnr_x264_256, psnr_xvid_256,psnr_mpeg2_256)
yvars <- c("psnr_x265_256","psnr_x264_256","psnr_xvid_256","psnr_mpeg2_256")
xvars <- c("x265","x264","xvid","mpeg2")
bmp(filename="boxplot_PSNR_256.bmp")
boxplot(journal_linear_data[,yvars], xlab=xvars, ylab="PSNR")
dev.off()
This is the image I get.
I want to have the corresponding values for each boxplot in x axis "x265","x264","xvid","mpeg2".
Do you have any idea how to fix this?
There are multiple ways of changing the labels for your boxplot variables. Probably the simplest way is changing the column names of your data frame:
colnames(journal_linear_data) <- c("x265","x264","xvid","mpeg2")
Even simpler: you could do this right at the creation of your data frame too:
journal_linear_data <- data.frame(x265=psnr_x265_256, x264=psnr_x264_256, xvid=psnr_xvid_256, mpeg2=psnr_mpeg2_256)
If you run into the problem of your labels not being shown or overlapping due to too few space, try rotating the x labels using the las parameter, e.g. las=2 or las=3.
In order to "convert" a ggplot2 graphic to a pdf LaTeX graphic with the tikzDevice package, I'd like to put the axis ticks labels between two $. Of course I can do it if I specify manually the tick labels, but how to do when using the automatic tick labels ? (in particular when using dates on the x-axis it is hard to specify manually the labels).
Update - solution with axis labels formatter
Based on #agstudy's answer, I have written the dollarify() formatter for numerical labels:
dollarify <- function(){
function(x) paste0("$",x,"$")
}
and the datify() formatter for dates:
datify <- function(){
function(x){
split <- stringr::str_split_fixed(as.character(x),"-",3)
out <- character(nrow(split))
for(i in 1:length(out)){
out[i] <- paste0("\\formatdate{", split[i,3], "}{", split[i,2], "}{", split[i,1], "}")
}
out
}
}
which generates a LaTeX code to be used with the datetime package:
\usepackage[ddmmyyyy]{datetime}
Below is a screenshot of a rendering, using the following scale for the x-axis :
scale_x_date(breaks="2 months", labels=datify())
It is not clear what you want to do but I think you are looking for an axis labels formatter.
## forma :you can give here any date format
dollar_date_format <- function (forma = "%H:%M"){
function(x) paste0("$",format(x,forma),"$")
}
Then using some data ( please provide reproducible example next time) you can use it like this:
DF <- data.frame(time=Sys.time()+1:10,count=1:10)
library(ggplot2)
qplot(x=time,y=count,data=DF)+
scale_x_datetime(labels = dollar_date_format(forma = "%M:%S"))+
xlab("Time (dollars)") +
theme(axis.text.x =element_text(size=20))
If you want to generically be able to modify the axis labels, you can run the plot, use ggplot_build() to get the plotted labels back, then add e.g. scale_x_continuous()/scale_x_date() with custom labels on the rendered breaks. You will need to tweak it depending on datatypes (look in the build variable to see what data's available).
You might want to use $x/y.labels or $x/y.major_source depending on datatype
x=c("2013-03-22","2013-04-24","2013-07-01","2013-09-13")
y=c(1,2,3,4)
#any ggplot object
g<-qplot(as.Date(x),y)
#call the rendered axis labels
build<-ggplot_build(g)
xrng<-data.frame(build$panel$ranges[[1]]$x.major_source,stringsAsFactors=FALSE)
yrng<-data.frame(build$panel$ranges[[1]]$y.labels,stringsAsFactors=FALSE)
colnames(xrng)<-"value"
colnames(yrng)<-"value"
#create custom labels
xrng$lab<-paste0("$",row.names(xrng),"$")
yrng$lab<-paste0("$",yrng$value,"$")
#re-render with custom labels
g+scale_x_date(breaks=as.Date(xrng$value),labels=xrng$lab) +
scale_y_continuous(breaks=as.numeric(yrng$value),labels=yrng$lab)
I have a plot which plots points with a particular symbol and color. I want my legend to show the exact same colors and symbols as those in the plot. I can do this manually, but I have over 50 plots to generate and data is going to be conually updated so I would like to automate the process. I tried to create a dictionary and wanted to search the dictionary. If the value was found in levels(Color_test), then color the symbol in legend the same as outlined in the dictionary.
My legend code is as follows:
legend(legend_X, legend_Y,
xjust=x_adj, yjust=y_adj,
levels(Color_test),
col=Labels.col,
pch=Labels.sym,
horiz=FALSE)
May be what you are looking for is some kind of merging your data with the dictionary. Here is how it is done with only colors as it is just an example
data <- data.frame(type = sample(letters[1:3],20,replace=T),
x = runif(20),
y = runif(20))
dict <- data.frame(type = letters[1:4],
color = c("red","green","blue","black"))
plot(data$x, data$y, col = merge(data,dict)$color)
legend("topleft",legend=dict$type, col=dict$color, pch=1)
Easily you can modify the legend so that is justs displays the actually used colors.
data_dict <- merge(data,dict)
plot(y~x, col=color, data=data_dict, pch=as.vector(type))
legend("topleft",legend=unique(data_dict$type), col=unique(data_dict$color), pch=1)
A minor question about plotting stacked barplot in R.
The stacked bars represent the series bottom-to-top.
But the legend always shows the series top-to-bottom. I think that is also true with ggplot2::geom_bar
Is there any nicer idiom than using rev(...) twice inside either legend() or barplot() as in:
exports <- data.frame(100*rbind('Americas'=runif(6),'Asia'=runif(6),'Other'=runif(6)))
colnames(exports) <- 2004:2009
series_we_want <- c(1,2,3)
barplot( as.matrix(exports[series_we_want,]), col=mycolors, ...)
legend(x="topleft", legend=rev(rownames(exports)[series_we_want]), col=rev(mycolors) ...)
(If you omit one of the rev()'s the output is obviously meaningless. Seems like an enhance case for adding a single flag yflip=TRUE or yreverse=TRUE)
This is what I got using your code:
exports <- data.frame(100*rbind('Americas'=runif(6),'Asia'=runif(6),'Other'=runif(6)))
colnames(exports) <- 2004:2009
series_we_want <- c(1,2,3)
barplot( as.matrix(exports[series_we_want,]))
legend(x="topleft", legend=rev(rownames(exports)[series_we_want]))
try this:
exports <- data.frame(100*rbind('Americas'=runif(6),'Asia'=runif(6),'Other'=runif(6)))
colnames(exports) <- 2004:2009
series_we_want <- c(1,2,3)
test_data<-as.matrix(exports[series_we_want])
barplot( test_data,
legend.text=as.character(rev(rownames(exports)[series_we_want])),
args.legend = list(x="topleft"))
seems to produce the legend in the opposite order of what you have