Plot percentages on y-axis - r

I'm plotting a graph using this
plot(dates,returns)
I would like to have the returns expressed as percentages instead of numbers. 0.1 would become 10%. Also, the numbers on the y-axis appear tilted 90 degrees on the left. Is it possible to make them appear horizontally?

Here is one way using las=TRUE to turn the labels on the y-axis and axis() for the new y-axis with adjusted labels.
dates <- 1:10
returns <- runif(10)
plot(dates, returns, yaxt="n")
axis(2, at=pretty(returns), lab=pretty(returns) * 100, las=TRUE)

If you use ggplot you can use the scales package.
library(scales)
plot + scale_y_continuous(labels = percent)

library(scales)
dates <- 1:100
returns <- runif(100)
yticks_val <- pretty_breaks(n=5)(returns)
plot(dates, returns, yaxt="n")
axis(2, at=yticks_val, lab=percent(yticks_val))
Highlights:
No need to explicitly add "%"
Manually fix the number of y-ticks to be consistent with further plots. Here I chose 5.
Combining two answers together #rengis #vladiim

Related

Stripcharts with same x-axis in R

I want to make a strip chart for each of the following two vectors with same x-axis using R.
Two vectors are:
x <- c(40,35,30,45,35,45,65,65,70,70)
y <- c(45,45,45,45,45,45,45,45,45,95)
When I made strip charts for the two, it came out like this:
How do I make it so that two x-axis will be the same?
Thank you
How do I make it so that two x-axis will be the same?
The stripchart() function takes an optional xlim parameter that lets you define the horizontal plot limits. For example:
x <- c(40,35,30,45,35,45,65,65,70,70)
y <- c(45,45,45,45,45,45,45,45,45,95)
par(bty="n", mfrow=c(2,1), mar=c(2,1,3,1)+0.1)
stripchart(x, xlim=c(20,100), method="stack", pch=16)
stripchart(y, xlim=c(20,100), method="stack", pch=21)

Y axis to percent using barplot [duplicate]

I'm plotting a graph using this
plot(dates,returns)
I would like to have the returns expressed as percentages instead of numbers. 0.1 would become 10%. Also, the numbers on the y-axis appear tilted 90 degrees on the left. Is it possible to make them appear horizontally?
Here is one way using las=TRUE to turn the labels on the y-axis and axis() for the new y-axis with adjusted labels.
dates <- 1:10
returns <- runif(10)
plot(dates, returns, yaxt="n")
axis(2, at=pretty(returns), lab=pretty(returns) * 100, las=TRUE)
If you use ggplot you can use the scales package.
library(scales)
plot + scale_y_continuous(labels = percent)
library(scales)
dates <- 1:100
returns <- runif(100)
yticks_val <- pretty_breaks(n=5)(returns)
plot(dates, returns, yaxt="n")
axis(2, at=yticks_val, lab=percent(yticks_val))
Highlights:
No need to explicitly add "%"
Manually fix the number of y-ticks to be consistent with further plots. Here I chose 5.
Combining two answers together #rengis #vladiim

rotate X axis labels 45 degrees on grouped bar plot R

How can I rotate the X axis labels 45 degrees on a grouped bar plot in R?
I have tried the solution suggested here but got something very messy, the labels seem to have been added multiple times (only showing the axis part to protect data privacy):
This solution (gridBase) was also unsuccessful for me, for some reason I get the following error:
"Cannot pop the top-level viewport (grid and graphics output mixed?)"
PS.
Most people seem to recommend this solution in R base but I am stuck with that too because I don't understand what data they are referring to (I need some kind of example data set to understand new command lines...).
Are these solutions not working because my barplot is a grouped barplot? Or should it work nevertheless? Any suggestions are welcome, I have been stuck for quite some time. Thank you.
[edit] On request I am adding the code that I used to generate the picture above (based on one of the text() solutions):
data <- #this is a matrix with 4 columns and 20 rows;
#colnames and rownames are specified.
#the barplot data is grouped by rows
lablist <- as.vector(colnames(data))
barplot(data, beside=TRUE, col=c("darkred","red","grey20","grey40"))
text(1:100, par("usr")[1], labels=lablist, srt=45, pos=1, xpd=TRUE)
I am not a base plot proficient, so maybe my solution is not very simple. I think that using ggplot2 is better here.
def.par <- par(no.readonly = TRUE)
## divide device into two rows and 1 column
## allocate figure 1 for barplot
## allocate figure 2 for barplot labels
## respect relations between widths and heights
nf <- layout(matrix(c(1,1,2,2),2,2,byrow = TRUE), c(1,3), c(3,1), TRUE)
layout.show(nf)
## barplot
par(mar = c(0,1,1,1))
set.seed(1)
nKol <- 8 ## you can change here but more than 11 cols
## the solution is not really readable
data <- matrix(sample(1:4,nKol*4,rep=TRUE),ncol=nKol)
xx <- barplot(data, beside=TRUE,
col=c("darkred","red","grey20","grey40"))
## labels , create d ummy plot for sacles
par(mar = c(1,1,0,1))
plot(seq_len(length(xx)),rep(1,length(xx)),type='n',axes=FALSE)
## Create some text labels
labels <- paste("Label", seq_len(ncol(xx)), sep = " ")
## Plot text labels with some rotation at the top of the current figure
text(seq_len(length(xx)),rep(1.4,length(xx)), srt = 90, adj = 1,
labels = labels, xpd = TRUE,cex=0.8,srt=60,
col=c("darkred","red","grey20","grey40"))
par(def.par) #- reset to default
Try the first answer:
x <- barplot(table(mtcars$cyl), xaxt="n")
labs <- paste(names(table(mtcars$cyl)), "cylinders")
text(cex=1, x=x-.25, y=-1.25, labs, xpd=TRUE, srt=45)
But change cex=1 to cex=.8 or .6 in the text() function:
text(cex=.6, x=x-.25, y=-1.25, labs, xpd=TRUE, srt=45)
In the picture you posted, it appears to me that the labels are just too big. cex sets the size of these labels.
I had the same problem with a grouped bar plot. I assume that you only want one label below each group. I may be wrong about this, since you don't state it explicitly, but this seems to be the case since your labels are repeated in image. In that case you can use the solution proposed by Stu although you have to apply colMeans to the x variable when you supply it to the text function:
x <- barplot(table(mtcars$cyl), xaxt="n")
labs <- paste(names(table(mtcars$cyl)), "cylinders")
text(cex=1, x=colMeans(x)-.25, y=-1.25, labs, xpd=TRUE, srt=45)

Segmenting X-axis label in an R plot

I've been working extensively with R lately and I have a nitpicky plotting question.
I've attached an image of my current plot as reference. As you can see, I've added vertical lines to segment parts of my data inputs. I have 200 'agents' and each of them comes from different categorical subsets which make them all a little different. So, my goal is to keep the bottom axis as the index of my 'agents' vector, but I'd like to add a label to each of my subdivisions at the bottom to make it a little clearer as to why I'm segmenting them with the vertical lines.
Any suggestions?
http://i.imgur.com/YGNdBhg.png?1?1971
You just need to call axis like this:
x = sin(1:100) + rnorm(100, 0,.125)
breaks = c(10,33,85, 96)
plot(x)
sapply(breaks, function(x){abline(v=x, lty=2)})
axis(1, breaks, as.character(breaks))
If you don't want the default ticks plotted at all (i.e. just the ticks in the "breaks" vector) you just need to modify this slightly:
plot(x, axes=F)
sapply(breaks, function(x){abline(v=x, lty=2)})
axis(1, breaks, as.character(breaks))
axis(2)
box()
You don't provide any example data or code, so the code I am sending is untested. I am calling the vector of vertical lines vertlines and the vector of labels labels. I define the midpoints of each category using the vertlines and the range of the agent values. Then I add them to the plot using the mtext() function. Give it a try.
vertlines <- c(40, 80, 120, 140, 160, 180)
labels <- letters[1:7]
labelx <- diff(c(1, vertlines, 200))/2 + c(1, vertlines)
mtext(labels, at=labelx, side=1, line=4)

Histogram with Logarithmic Scale and custom breaks

I'm trying to generate a histogram in R with a logarithmic scale for y. Currently I do:
hist(mydata$V3, breaks=c(0,1,2,3,4,5,25))
This gives me a histogram, but the density between 0 to 1 is so great (about a million values difference) that you can barely make out any of the other bars.
Then I've tried doing:
mydata_hist <- hist(mydata$V3, breaks=c(0,1,2,3,4,5,25), plot=FALSE)
plot(rpd_hist$counts, log="xy", pch=20, col="blue")
It gives me sorta what I want, but the bottom shows me the values 1-6 rather than 0, 1, 2, 3, 4, 5, 25. It's also showing the data as points rather than bars. barplot works but then I don't get any bottom axis.
A histogram is a poor-man's density estimate. Note that in your call to hist() using default arguments, you get frequencies not probabilities -- add ,prob=TRUE to the call if you want probabilities.
As for the log axis problem, don't use 'x' if you do not want the x-axis transformed:
plot(mydata_hist$count, log="y", type='h', lwd=10, lend=2)
gets you bars on a log-y scale -- the look-and-feel is still a little different but can probably be tweaked.
Lastly, you can also do hist(log(x), ...) to get a histogram of the log of your data.
Another option would be to use the package ggplot2.
ggplot(mydata, aes(x = V3)) + geom_histogram() + scale_x_log10()
It's not entirely clear from your question whether you want a logged x-axis or a logged y-axis. A logged y-axis is not a good idea when using bars because they are anchored at zero, which becomes negative infinity when logged. You can work around this problem by using a frequency polygon or density plot.
Dirk's answer is a great one. If you want an appearance like what hist produces, you can also try this:
buckets <- c(0,1,2,3,4,5,25)
mydata_hist <- hist(mydata$V3, breaks=buckets, plot=FALSE)
bp <- barplot(mydata_hist$count, log="y", col="white", names.arg=buckets)
text(bp, mydata_hist$counts, labels=mydata_hist$counts, pos=1)
The last line is optional, it adds value labels just under the top of each bar. This can be useful for log scale graphs, but can also be omitted.
I also pass main, xlab, and ylab parameters to provide a plot title, x-axis label, and y-axis label.
Run the hist() function without making a graph, log-transform the counts, and then draw the figure.
hist.data = hist(my.data, plot=F)
hist.data$counts = log(hist.data$counts, 2)
plot(hist.data)
It should look just like the regular histogram, but the y-axis will be log2 Frequency.
I've put together a function that behaves identically to hist in the default case, but accepts the log argument. It uses several tricks from other posters, but adds a few of its own. hist(x) and myhist(x) look identical.
The original problem would be solved with:
myhist(mydata$V3, breaks=c(0,1,2,3,4,5,25), log="xy")
The function:
myhist <- function(x, ..., breaks="Sturges",
main = paste("Histogram of", xname),
xlab = xname,
ylab = "Frequency") {
xname = paste(deparse(substitute(x), 500), collapse="\n")
h = hist(x, breaks=breaks, plot=FALSE)
plot(h$breaks, c(NA,h$counts), type='S', main=main,
xlab=xlab, ylab=ylab, axes=FALSE, ...)
axis(1)
axis(2)
lines(h$breaks, c(h$counts,NA), type='s')
lines(h$breaks, c(NA,h$counts), type='h')
lines(h$breaks, c(h$counts,NA), type='h')
lines(h$breaks, rep(0,length(h$breaks)), type='S')
invisible(h)
}
Exercise for the reader: Unfortunately, not everything that works with hist works with myhist as it stands. That should be fixable with a bit more effort, though.
Here's a pretty ggplot2 solution:
library(ggplot2)
library(scales) # makes pretty labels on the x-axis
breaks=c(0,1,2,3,4,5,25)
ggplot(mydata,aes(x = V3)) +
geom_histogram(breaks = log10(breaks)) +
scale_x_log10(
breaks = breaks,
labels = scales::trans_format("log10", scales::math_format(10^.x))
)
Note that to set the breaks in geom_histogram, they had to be transformed to work with scale_x_log10

Resources