I am very new to R, so I'm struggling here a bit and I haven't found an answer to my problem.
I'm trying to produce a simple bar-chart in R, and I have set my x-axis variable labels to be vertical, using las=2. I then changed the margins for the barplot so that the labels would not overlap the xlab label, using par(mar=c(20,15,5,3)) and par(mgp=c(6,1,0)).
I would like to add a legend to this, but the one I have has adopted the margin dimensions of the graph itself, so that it appears too big and does not fit. I tried using cex but that only affects the text in the legend. Is there anyway for me to change the legend margins (or the graph margins) independently?
Here's what I have coded:
par(mar=c(20,15,5,3))
par(mgp=c(6,1,0))
par(xpd=TRUE)
barplot(
names.arg=c("Africa", "Central America, South America, Caribbean",
"Middle East", "Central and Eastern Europe",
"South and East Asia"),
cex.names=0.8, las=2, t(YLL),
ylab="Percentage (%)", ylim=c(0,100), main="", beside=TRUE,
col= c("green4", "orange"),xlab="Regions", mar=c(20,15,5,3)
)
legend(
10, 100,
legend=c("Communicable diseases", "Communicable diseases"),
fill= c("green4", "orange"), cex=0.7
)
I will really appreciate the help, thanks.
You can also use the arguments of legend function: y.intersp, x.intersp and text.width for reduce the size of the legend.
Here an example:
set.seed(55) # Set the seed of R‘s random number generator
x <- 1:10
y <- runif(10, min=0, max=100) # Generating random numbers
z <- runif(10, min=0, max=100) # Generating random numbers
plot(x,y, type="l", ylim=c(0,100), ylab="y and z")
par(new=TRUE)
plot(x,z, type="l", col="red", ylim=c(0,100), ylab=NA, xaxt='n', yaxt='n')
legend("topright", c("y","z"), lty="solid", col=c("black", "red"))
And same code modifiying the legend function:
set.seed(55) # Set the seed of R‘s random number generator
x <- 1:10
y <- runif(10, min=0, max=100) # Generating random numbers
z <- runif(10, min=0, max=100) # Generating random numbers
plot(x,y, type="l", ylim=c(0,100), ylab="y and z")
par(new=TRUE)
plot(x,z, type="l", col="red", ylim=c(0,100), ylab=NA, xaxt='n', yaxt='n')
legend("topright", c("y","z"), lty="solid", col=c("black", "red"), y.intersp=0.5,x.intersp=0.5,text.width=0.1)
I don't know if I understood your problem correctly, but maybe you can try x.intersp or y.intersp to modify the spacing in the x and y axis of your legend. For example, you could add x.intersp=0.5 to bring the elements of your legend closer in the x axis.
If this does not work and you provide a screenshot, maybe I could try to help you better.
Related
I'm creating a graphic that has a few different graph elements, using layout() to define plotting regions. I have a separate region for labels that need to align to bars on a barplot in an adjacent plotting region.
I can take a guess at where to plot the labels so that they line up - but the number of these locations will vary so this is not an ideal solution.
Here's an example of what I'm trying to do:
labs <- paste("Some text", letters[1:9])
datA <- table(sample(letters[1:9], size=200, replace=TRUE, prob=rep(c(0.1,0.2,0.3),3)))
layout(matrix(c(1,2,3,3), 2, 2, byrow=TRUE), widths=c(1,2), heights=c(6,1))
plot.new()
text(x=1, y=seq(0.05,1.0,0.111), labels=labs, adj=1, cex=1.4)
barplot(datA, horiz=TRUE, las=1, axes=F, yaxt="n")
How can I find the correct values to plot the labels?
(I'm aware that it looks like this can be solved by just plotting the labels with the barplot - this is not a viable solution for what I'm doing).
The output of barplot gives the heights so:
bp <- barplot(datA, horiz=TRUE, las=1, axes=F, yaxt="n")
text(0*bp, bp, labs, col = "blue", pos = 4)
I am finishing with my script, but I cannot set an angle for x labels. I would like to use it for my data in specific index position:
INPUT:
xlabel <- (0,100,200,250,336)
xlabel.popis <- ("TATA","MAMA","OND","KOKO","LOLO")
OUTPUT:
Will be plotted xlabel.popis on specific xlabel postion on x axis (x axis is index line (0..500)) and xlabel.popis will have vertical rotation.
I tried:
plot(read.table(files2[i],header=F,sep="\t")$V7,main=file_bez2[i], axes=FALSE)
xlabel <- (0,100,200,250,336)
xlabel.popis <- ("TATA","MAMA","OND","KOKO","LOLO")
axis(1, at=seq_along(xlabel),labels=as.character(xlabel.popis, las=2, cex.label=90))
or I tried no axis but mtext(as.character(xlabel.popis),side=1,line=1.1,at=xlabel,srt=90)
Nothing worked, could you help me, It will be better for me with axis definition.And par() definiton did not work too.
Thank you so much
I believe you need to add labels with the text function after a call to axis.
example:
xlabel <- c(0,100,200,250,336)
xlabel.popis <- c("TATA","MAMA","OND","KOKO","LOLO")
plot(range(xlabel), c(1,1), t="l", xaxt="n", xlab="")
axis(1, at=xlabel, labels=FALSE)
text(x=xlabel, y=par()$usr[3]-0.1*(par()$usr[4]-par()$usr[3]),
labels=xlabel.popis, srt=45, adj=1, xpd=TRUE)
If you just want 90° rotation, consider the las argument:
plot(range(xlabel), c(1,1), t="l", xaxt="n", xlab="")
axis(1, at=xlabel, labels=xlabel.popis, las=2)
I have combined two data sets into one graph and I would like to add the corresponding pch symbols right into the axis labels.
Now, I know that solutions using text() instead of xlab and ylab and Hershey vector fonts (instead of citing a pch=16, etc.) are given here and here but the symbols appear kinda wonky-shaped. Does anyone have a more "well-rounded" solution?
thinkoholic.com's reproducible example,
par(mar=c(5,5,2,5))
# create data and plot circles
x <- seq(0,5,0.5)
y <- seq(0,5,0.5)
plot(x,y, xlab="", ylab="")
#create random data and add bullets (pch=19)
x <- rnorm(20,2.5)
y <- rnorm(20,2.5)
points(x,y, pch=19)
#add y axis on right side
axis (side = 4)
#create text with symbols
text(-1,2.5,"\\#H0850 y1 axis text", vfont=c("sans serif","plain"), cex=1.25, adj=0.5, srt=90, xpd=TRUE)
text(6,2.5,"\\#H0902 y2 axis text", vfont=c("sans serif","plain"), cex=1.25, adj=0.5, srt=90, xpd=TRUE)
text(2.5,-1,"x axis text", vfont=c("sans serif","plain"), cex=1.25, adj=0.5, srt=0, xpd=TRUE)
If you insist on doing this:
par(mar=c(5,5,2,5), xpd=TRUE)
x <- seq(0,5,0.5)
y <- seq(0,5,0.5)
plot(x,y, xlab="", ylab="")
text(-1,2.5,"y axis text", cex=1.25, adj=0, srt=90)
points(-1,2.4)
This should work:
mtext(paste0("your label text", " (", intToUtf8(9679), ")"), side = 2, line=2.5)
Assuming I have two data sets I'd like to plot in one plot.
For instance something like this:
low <- runif(10,min=10, max=50)
high <- runif(10,min=10000, max=11000)
plot(
high,
type="l",
ylim=c(0,11000)
)
lines(low, type="l")
I dont want the y-axis to show all values in between these samples because the way it is, the low data would appear as flat line, even though there are variations.
Therefore, the axis should have a finer grained ticks between 10-50, and should omit values between 50 and 10000. Then again, the interval [10000-11000] should have finer grained ticks, too. Thus, variations for the low sample are also visible.
Is there any way to achieve this behavior?
If found this, bt
Could this be useful...?
set.seed(001)
low <- runif(10,min=10, max=50)
high <- runif(10,min=10000, max=11000)
plot(
high,
type="l",
ylim=c(0,11000)
)
lines(low, type="l")
plot(high,
type="l",
col="red",
bty='l',
ylab='', xlab='',
las=1,
cex.axis=.75)
par(new=TRUE)
plot(low,
type="l",
col="blue",
bty='n',
xaxt="n",
yaxt="n",
xlab="", ylab="",
cex.axis=.75)
axis(4, las=1, cex.axis=.75)
legend('topright', c('high', 'low'), col=c('red', 'blue'), lty=1, bty='n', cex=.75)
Questions of good graphical practice aside, this can be done using the plotrix package:
low <- runif(10,min=10, max=50)
high <- runif(10,min=10000, max=11000)
y <- c(low,high)
x <- rep(1:10,times = 2)
library(plotrix)
yl <- c(pretty(5:70,2),pretty(9900:11000,5))
gap.plot(x,y,
gap = c(70,9900),
gap.axis = "y",
ytics = yl,
type = "l")
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