Barplot: Greek letters on y axis in R - r

This is a follow-up question to my other question on barplots:
Tornado plot in R
I realized the question about getting greek letters on the y-axis needed to be asked as an own question.
The question is:
I have the following barplot and need to change the y-axis to respective greek letters (and a V with a bar over).
I use the following code:
# Tornado plot
data <- matrix(c(-0.02,0.02,-0.01,0.01,-0.03,0.02,-0.01,0.04), ncol = 4)
rownames(data) <- c('+10%','-10%')
colnames(data) <- c('V_bar', 'alpha', 'rho','xi')
x <- seq(-0.04,0.04, length=10)
barplot(data[1,], horiz = T, las=1, xlim = c(-0.04,0.04), xaxt='n', ylab='',
beside=T, col=c('springgreen'))
barplot(data[2,], horiz = T, las=1, xlim = c(-0.04,0.04), xaxt='n',
yaxt='n', #To prevent double printing of y-labels.
beside=T, col=c('indianred2'), add = TRUE)
axis(1, at=pretty(x), lab=paste0(pretty(x) * 100," %"), las=TRUE)
To get the greek letters I have tried the following:
barplot(data[2,], horiz = T, las=1, xlim = c(-0.04,0.04), xaxt='n',
yaxt= c(expression(bar(V)), expression(alpha),expression(rho), expression(xi)),
beside=T, col=c('indianred2'), add = TRUE))
and
axis(2, at=c(1:4), lab = expression(xi ~ rho ~ alpha ~ bar(V)), las=T)
or
axis(2, at=pretty(x), lab = paste0(expression(xi ~ rho ~ alpha ~ bar(V)), las=T))
But no success. Anyone now the trick?
Note. I have seen this question: Adding greek character to axis title
But it focuses on the labels, not the y-axis "values".
Also, I have tried something like Putting greek letters in column names
with no success.

There's no need to call axis for labeling of the bars if you provide the argument names.arg to barplot:
barplot(data[1,], horiz = T, las=1, xlim = c(-0.04,0.04), xaxt='n', ylab='',
beside=T, col=c('springgreen'),
names.arg=c(expression(xi),expression(rho), expression(alpha), expression(bar(V))))

You just need to pass lab in axis as a vector of expressions.
axis(2, at=c(1:4), lab = c(expression(xi),
expression(rho), expression(alpha), expression(bar(V))), las=T)
Then you can play with the settings of the axis as needed.

Related

How can I get to print ALL of the labels in the x axis in R?

Please understand that this is not a serious exercise or any research project, and I would ask the context be left to the side as ane
The issue is that when I try to plot the values on a column against the names of the countries, some of them are excluded from the x axis, and I don't know why.
Here is the data.
And this is the code:
require(RCurl)
require(foreign)
require(tidyverse)
x = getURL("https://raw.githubusercontent.com/RInterested/PLOTS/master/drinks_csv.csv")
data <- read.csv(textConnection(x))
data <- data[,c(1:5,8)]
plot(data$country,data$cases,las=2, xlab="", ylab="")
How do I either print different alternate countries, or all of them in the x axis?
Well, there are 169 countries, so they'd have to be pretty small to print all of them.
plot(data$country,data$cases,las=2, xlab="", ylab="", xaxt = 'n')
axis(1, at = 1:length(data$country), labels = data$country, cex.axis = 0.1, las = 2)
We can select which countries to plot x-axis ticks for by finding their indices in the rows of data$country and then using axis to plot those selected countries.
my.countries <- match(c("poland","japan","togo", "belarus"),data$country)
plot(data$country,data$cases,las=2, xlab="", ylab="", xaxt = 'n')
axis(1, at = my.countries, labels = data$country[my.countries], las = 2)

how to plot matlab style log-log plot using R plot

ENV
R version 3.3.1
MAC OSX 10.9.4
I would like to plot a style like figure below, which is plotted by matlab.
There is full grid on the plot with customized axis range (e.g. $10^0~10^{-4}$) and axis label (e.g. 10^0 10^1 10^-2 10^-3 10^-4 10^-5). There are ten ticks between 10^0 and 10^1 and also other labels. Similar for y axis.
Expected:
I tried:
initial.dir<-getwd()
setwd("/Rworks/bin")
sink("r.o")
pk <- read.table("2017.file)
rownames(pk)<-c("k","pk")
d.f <- data.frame(t(pk))
png(file="m.png")
plot(
d.f$k,
d.f$pk,
type = "n",
log = "xy",
xlim = c( 10^0, 10^2),
ylim = c( 0.00001, 1),
)
lines( d.f$k, d.f$pk, col = "green4", lty = "dotted")
points( d.f$k, d.f$pk, bg = "limegreen", pch = 21 )
box()
dev.off
sink()
setwd(initial.dir)
I got:
The axis and axis label and the ticks and grid is not what I want. Can anyone can give an advices? Thanks.
Worst case scenario, you can just draw the axes and background lines yourself.
plot(
x=c(1,2), y=c(0.6,0.2),
pch=21, bg="red",
log = "xy",
xlim = c( 10^0, 10^2),
ylim = c( 0.00001, 1),
xaxt="n", yaxt="n",
xlab="", ylab="",
yaxs="i"
)
lines(x=c(1,2), y=c(0.6,0.2))
axis(1, at=10^(0:2),
labels=expression(10^0, 10^1, 10^2))
axis(2, at=10^(-5:0), las=1,
labels=expression(10^-5, 10^-4, 10^-3, 10^-2, 10^-1, 10^0))
abline(h=outer((1:10),(10^(-5:-1))), col="#00000033", lty=2)
abline(v=outer((1:10),(10^(0:1))), col="#00000033", lty=2)
Here's an example - it's not exactly what you want (e.g. you could play around with theme options such as panel.grid.minor to get dotted grid lines), but it's most of the way there.
Exponential-format axis tick labels, from here:
fancy_scientific <- function(l) {
# turn in to character string in scientific notation
l <- format(l, scientific = TRUE)
# quote the part before the exponent to keep all the digits
l <- gsub("^(.*)e", "'\\1'e", l)
# turn the 'e+' into plotmath format
l <- gsub("e", "%*%10^", l)
# return this as an expression
parse(text=l)
}
Manual ticks from #G5W's answer: might be possible to write a function to do this automatically, or one might exist somewhere.
yticks = outer((1:10),(10^(-5:-1)))
xticks = outer((1:10),(10^(0:1)))
Draw the plot (with #G5W's sample mini-data)
library(ggplot2)
ggplot(data.frame(x=1:2,y=c(0.6,0.2)),
aes(x,y))+
geom_point(colour="red")+
scale_x_log10(limits=c(1,100),labels=fancy_scientific,
minor_breaks=xticks)+
scale_y_log10(limits=c(1e-5,1),labels=fancy_scientific,
minor_breaks=yticks)+
theme_bw()

Reverse the scale of the x axis in a plot

I have created a plot in R and my own custom x and y axes. I would like the x axis to be displayed in a reverse order (1-0 by -.02). I have read numerous posts and threads that suggest using xlim and reverse range but I just can't seem to make it work. Once plotted I am also converting the axes labels to percentages by multiplying by 100 (as you will see in the code). Here is what I have so far;
plot(roc.val, xlab = "Specificity (%)", ylab = "Sensitivity (%)", axes = FALSE)
axis(2, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
axis(1, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
How can I reverse the x axis scale so that the values begin at 100 and end at 0 with increments of 20?
I think this creates a plot in which the y-axis is in reverse order:
x <- seq(-4, 4, length = 10)
y <- exp(x) / (1 + exp(x))
plot(x,y, ylim = rev(range(y)))
This removes the axis values:
x <- seq(-4, 4, length = 10)
y <- exp(x) / (1 + exp(x))
plot(x,y, ylim = rev(range(y)), labels = FALSE)
I guess you can assign the axis values you want then with a variation of your lines:
axis(2, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
axis(1, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
df <- data.frame(x=seq(0,1, length.out=50), y=seq(0, 1, length.out=50))
plot(df)
df$x1 <- (max(df$x) - df$x)/ (max(df$x) - min(df$x))
plot(df$x1, df$y, axes=F, xlab = "Specificity (%)", ylab = "Sensitivity (%)")
axis(2, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
axis(1, at = seq(0,1,by=.2), labels = paste(100*seq(1,0, by=-.2)), tick = TRUE)
Adapting Mark Miller's answer to solve a similar problem (I found this topic by looking for the solution) and I found a variation of his solution in https://tolstoy.newcastle.edu.au/R/help/05/03/0342.html.
Basically if you want to reverse the X-axis values in the plot, instead of using ylim=rev(range(y)), you can use xlim=rev(c(-4,4)).
x <- seq(-4, 4, length = 10)
y <- exp(x) / (1 + exp(x))
par(mfrow=c(1,2))
plot(x, y, ylim=range(y), xlim=c(-4, 4))
plot(x, y, ylim=range(y), xlim=rev(c(-4, 4)))
plot1
And if you want to keep the x-axis values in the true order, you can use this:
par(mfrow=c(1,1))
plot(x, y, ylim=range(y), xlim=c(-4, 4), axes=FALSE)
par(new=TRUE)
plot(-100, -100, ylim=range(y), xlim=c(-4, 4), axes=FALSE, xlab="", ylab="", main="")
axis(1, at = seq(-4,4,by=1), labels = seq(-4,4,by=1), tick = TRUE)
axis(2, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
plot2
I'm posting this solution because I needed something very straightforward to solve my problem. And the solution for it needed the plot with the X-axis value in the correct order (and not reversed).
First, check out the ggplot2 library for making beautiful and extendable graphics. It is part of the Tidyverse approach to R and a gamechanger if you have not been exposed to it.
For example, to solve your issue using ggplot, you simply add the term scale_x_reverse() to your graphic.
See: http://ggplot.yhathq.com/docs/scale_x_reverse.html

can't delete y axis label in plot.gbm

Run-on question following this problem setting axis widths in gbm.plot; I'm now using plot.gbm directly and don't seem to be able to remove the y axis label, which seems to be set within the plot.gbm function code.
png(filename="name.png",width=4*480, height=4*480, units="px", pointsize=80, bg="white", res=NA, family="", type="cairo-png")
par(mar=c(2.6,2,0.4,0.5), fig=c(0,1,0.1,1), las=1, lwd=8, bty="n", mgp=c(1.6,0.5,0))
plot.gbm(my_gbm_model,1,return.grid=FALSE, write.title=F,lwd=8, ylab=F, axes=F, ylabel=FALSE, ylabel="")
axis(1, lwd.ticks=8, lwd=8, labels=FALSE)
axis(2, lwd.ticks=8, lwd=8, labels=NA, ylab=FALSE,ylabel=FALSE)
dev.off()
Result:
The y axis label is still there despite all my atempts to remove it through par and plot and axis. I could try burrowing into the function and changing this (and similar) lines:
print(stripplot(X1 ~ temp | X2 * X3, data = X.new,
xlab = x$var.names[i.var[i[1]]],
ylab = paste("f(", paste(x$var.names[i.var[1:3]], collapse = ","), ")", sep = ""),
...))
...but I've been advised against such practices. Any thoughts why this might be working? Simply that the function overrides the setting?
Reproducibility:
#core data csv: https://drive.google.com/file/d/0B6LsdZetdypkWnBJVDJ5U3l4UFU
#(I've tried to make these data reproducible before and I can't work out how to do so)
library(dismo)
samples <- read.csv("data.csv", header = TRUE, row.names=NULL)
my_gbm_model <- gbm.step(data=samples, gbm.x=1:6, gbm.y=7, family = "bernoulli",
tree.complexity = 2, learning.rate = 0.01, bag.fraction = 0.5)
The problem is that plot.gbm just isn't a very R-like function. Since anyone can submit a package to CRAN it's not required that they follow traditional R patterns and that looks like what happened here. If you step though plot.gbm with your sample data, you see that ultimately the plotting is done with
plot(X$X1, X$y, type = "l", xlab = x$var.names[i.var], ylab = ylabel)
and the ylabel is set immediately before with no option to disable it. The authors simply provided no standard way to suppress the ylab for this particular plotting function.
In this case the easiest way might just be to reduce the left margin so the label prints off the plot. Seems like
par("mar"=c(5,2.2,4,2)+.1, fig=c(0,1,0.1,1), las=1, lwd=8, bty="n")
plot.gbm(my_gbm_model,1,return.grid=FALSE, write.title=F,lwd=8, ylab="", axes=F)
axis(1, lwd.ticks=8, lwd=8, labels=FALSE)
axis(2, lwd.ticks=8, lwd=8, labels=FALSE)

Plotting a grid behind data, not in front in R

I like to produce my own grid lines when plotting so I can control tick marks, etc. and I am struggling with this with the 'hist' plotting routine.
hist(WindSpeed, breaks=c(0:31), freq=TRUE, col="blue", xaxt="n", yaxt="n", xlab="Wind Speed (m/s)",main="Foo", cex.main=1.5, cex.axis=1, cex.lab=1, tck=1, font.lab=2)
axis(1, tck=1, ,col.ticks="light gray")
axis(1, tck=-0.015, col.ticks="black")
axis(2, tck=1, col.ticks="light gray", lwd.ticks="1")
axis(2, tck=-0.015)
minor.tick(nx=5, ny=2, tick.ratio=0.5)
box()
Plot:
I have then just been able to use the 'lines' or 'points' command to replot the data over top for other types of plots, but with the histogram its not so easy.
Any help would be great.
I added my code below and image based upon John's response...
I added my code below and image based upon John's response...
hist(WindSpeed, breaks=30, freq=TRUE, col="blue", xaxt="n", yaxt="n", xlab="Wind Speed (m/s)",main="Foo", cex.main=1.5, cex.axis=1, cex.lab=1, font.lab=2)
axis(1, tck=1, col.ticks="light gray")
axis(1, tck=-0.015, col.ticks="black")
axis(2, tck=1, col.ticks="light gray", lwd.ticks="1")
axis(2, tck=-0.015)
minor.tick(nx=5, ny=2, tick.ratio=0.5)
box()
hist(WindSpeed, add=TRUE, breaks=30, freq=TRUE, col="blue", xaxt="n", yaxt="n", xlab="Wind Speed (m/s)", main="Foo", cex.main=1.5, cex.axis=1, cex.lab=1, font.lab=2)
Actually, R has a way to do this! It's the panel.first argument to plot.default, which hist calls to do most of the work. It takes an expression which is evaluated "after the plot axes are set up but before any plotting takes place. This can be useful for drawing background grids or scatterplot smooths," to quote from ?plot.default.
hist(WindSpeed, breaks=c(0:31), freq=TRUE, col="blue", xaxt="n", yaxt="n",
xlab="Wind Speed (m/s)", main="Foo",
cex.main=1.5, cex.axis=1, cex.lab=1, tck=1, font.lab=2,
panel.first={
axis(1, tck=1, col.ticks="light gray")
axis(1, tck=-0.015, col.ticks="black")
axis(2, tck=1, col.ticks="light gray", lwd.ticks="1")
axis(2, tck=-0.015)
minor.tick(nx=5, ny=2, tick.ratio=0.5)
box()
})
See How do I draw gridlines using abline() that are behind the data? for another question that uses this method.
This is relatively easy.
Generate the histogram but don't plot it.
h <- hist(y, plot = FALSE)
Now generate your base plot... I've added some features to make it look more like a standard historgram
plot(h$mids, h$counts, ylim = c(0, max(h$counts)), xlim = range(h$mids)*1.1,
type = 'n', bty = 'n', xlab = 'y', ylab = 'Counts', main = 'Histogram of y')
add your grid
grid()
add your histogram
hist(y, add = TRUE)
Or, as I discovered through this process... you can do it even easier
hist(y)
grid()
hist(y, add = TRUE, col = 'white')
This last method is just redrawing the histogram over the grid.
In R, order matters when you plot. As you've discovered, adding things to a plot adds on top of what you've plotted before. So we need a way to plot the grid first and then the histogram. Try something like this:
plot(1:10,1:10,type = "n")
grid(10,10)
hist(rnorm(100,5,1),add = TRUE)
I haven't recreated your example, since it isn't reproducible, but this general idea should work. But the key idea is to create an empty plot with the correct dimensions using the type = "n" option to plot, then add the grid, then add the histogram using the add = TRUE argument.
Note that the add argument is actually for plot.histogram, hist passes it along via ....
The base graphics solution suggested by #joran is fine. Alternatives:
d <- data.frame(x=rnorm(1000))
library(lattice)
histogram(~x,data=d,panel=function(...) {
panel.grid(...)
panel.histogram(...) }
)
Or:
library(ggplot2)
qplot(x,data=d,geom="histogram",binwidth=0.1)+theme_bw()+
labs(x="Wind speed", y="Frequency")
(But of course you will have to learn all the details of adjusting labels, titles, etc. ... I'm not actually sure how to do titles in ggplot ...)
Another methods for grid lines in background:
A)
hist( y, panel.first=grid() ) # see: help( plot.default )
box()
B)
plot.new() # new empty plot
nv <- length( pretty(x) ) - 1 # number of vertical grid lines (or set by hand)
nh <- length( pretty(y) ) - 1 # number of horizontal grid lines (or set by hand)
grid( nx = nv, ny = nh ) # preplot grid lines
par( new = TRUE ) # add next plot
plot( x, y ) # plot or hist, etc
box() # if plot hist
Arbitrary lines in background with abline:
C)
How do I draw gridlines using abline() that are behind the data?
D)
# first, be sure there is no +/-Inf, NA, NaN in x and y
# then, make the container plot with two invisible points:
plot( x = range( pretty( x ) ), y = range( pretty( y ) ), type = "n", ann = FALSE )
abline( h = hlines, v = vlines ) # draw lines. hlines, vlines: vectors of coordinates
par( new = TRUE ) # add next plot. It is not necessary with points, lines, segments, ...
plot( x, y ) # plot, hist, etc
box() # if plot hist

Resources