Suppose data
set.seed(42)
a <- rnorm(100)
b <- rnorm(100)+1
which I would like to plot side-by-side using multhist().
multhist(list(a,b), yaxs="i")
Now I would like to draw a box around them
box(which = "plot", lty = "solid")
which gives me
with some space between the bottom line of the box and the bars.
Had I used hist() to plot only one graph, the ouput would have been without gap between box and bars:
Is there a different trick to get such an output in multhist()?
I think setting ylim mentioned by #KamranEsmaeili is a standard solution. Here I provided a tricky way that doesn't require manually setting the upper limit 40.
multhist() is based on the built-in barplot() and it always sets the lower limit of y-coordinate of the plotting region less than 0. You can use par("usr")[3] to check this fact. I just came up with a tricky method that adjusts the box type to "7" to suppress the bottom line and add a new bottom line at 0 by abline(h = 0).
library(plotrix)
set.seed(42)
a <- rnorm(100)
b <- rnorm(100) + 1
multhist(list(a,b))
#---------------------------------
box(bty = "7") # bty is one of "o"(default), "l", "7", "c", "u", and "]".
abline(h = 0)
Edit
If you don't like the right line extending beyond the x axis, then you can replace box() with rect() so that you can specify positions of four sides by yourself. Remember to add xpd = TRUE, or the line width will look thinner than y-axis.
multhist(list(a,b))
x <- par("usr")
rect(x[1], 0, x[2], x[4], xpd = TRUE)
Just add "space=c(0,0)" and "ylim" and you good to go:
multhist(list(a,b), yaxs="i", space=c(0,0), ylim=c(0,40))
Related
Hi I guess that I have quite a rudimentary question here.
I have a plot like this
but as you could easily notice, some of the label could not be displayed (some are overlapped with the symbols, some are just out of the figure frame)
I noticed that there are some way to adjust the position of labels
text(tsne_out$Y[,1], tsne_out$Y[,2], labels=samplegrouptry, pos=1)
for example, I could specify the the value of "pos" (from 1 to 4). I guess they are good enough in most cases .But I wonder whether there are some better ways to do that.
Any suggestion, thanks!
Following the suggestion from
vas_u Through change the axis ranges as well as "pos", I could get better plot:
One way around the problem would be to enlarge the axes of the plot.
Your example approximately reproduced with dummy data:
x <- rnorm(16, mean = 0)
y <- rnorm(16, mean = 1)
# Initial scatterplot with text labels out of plot area:
plot(x, y, pch = 16)
text(x, y, labels = paste("Name", 1:16), pos = 1) # Some labels outside plot area
# Second plot with the X and Y axes gently expanded:
plot(x, y, pch = 16,
xlim = 1.1*range(x),
ylim = 1.1*range(y))
text(x, y, labels = paste("Name", 1:16), pos = 1) # Labels now fit inside!
I hope this helps.
I want to get rid the small margin close to zero on X and Y value (red line on pic), and plot ONLY what is showed in red square.
I tried setting par(mar = rep(0, 4) and xlim=c(0, ...), ylim=c(0, ...) but R still keeps adding this tiny margin. How to get rid of it?
EDIT:
another point of view on my problem:
after running:
require(plotrix)
axisRange <- c(0,500)
plot(NULL, xlim = axisRange, ylim=axisRange)
draw.circle(0, 0, 200, col = "white", border = "red")
I end up with a circle positioned not in "true" 0,0 point:
EDIT2:
Actually what I want to do, is to plot circles of different radius, and save it as an image. That is why I care about the margins.
I end up with something like this (spots on the corners are for the reference):
And should be more like this:
You can set the xaxs and yaxs arguments to "i" as opposed to the default of "r". From the par help page:
Style "r" (regular) first extends the data range by 4 percent at each
end and then finds an axis with pretty labels that fits within the
extended range.
Style "i" (internal) just finds an axis with pretty labels that fits
within the original data range.
library(plotrix)
axisRange <- c(0,500)
par(mar = rep(0,4))
plot(NULL, xlim = axisRange, ylim=axisRange, xaxs = "i", yaxs = "i")
draw.circle(0, 0, 200, col = "white", border = "red")
Gives:
Consider the following vector:
vec <- c(-0.137042293280008 ,-0.0085530023889108 ,7.696986350237e-05 ,9.85275557252565e-05 ,0.000246261331270769 ,-0.0013658222244989 ,0.00117046787783182 ,-0.000423648394606887 ,-0.000112607126438433 ,0.00212185051472275 ,-0.000110104526782098)
names(vec) <- paste("var", 1:length(vec), sep = " ")
I would like to plot vec using a bar plot in R. However, as you can see, there is one or two values that are extreme compared to the rest of the vector. When the bar plot is drawn, the small values barely show on the graph.
par(xaxs='i',yaxs='i', mai = c(0.5,2,0.5,1.5))
bp2 <- barplot(vec, horiz = TRUE, col = "lightblue4", border = "lightblue4", yaxt = 'n', cex.axis = 0.7)
axis(2, at = bp2, labels = names(vec), tick = FALSE, las = 2, cex.axis = 0.7)
Is there a way to better display the chart? For example, is there a way to eventually split the x-axis? The graph below is an (unrelated) example, but it shows how the y-axis in this case is split to allow for all values to show on the graph.
P.S: Plotting with a log-scale is not an option in my case, as some of the vector values are negative.
Thank you!
You need gap.barplot from plotrix package. Take a look at this:
library(plotrix)
gap.barplot(vec,gap=c(-0.12,-0.04),xlab="Index",ytics=c(-0.04,-0.02,0),
ylab="",main="Barplot with gap", horiz=TRUE)
Modify gap and ytics argument to get the desired aesthetic for your plot.
I used this code to make this plot:
plot(p, cv2,col=rgb(0,100,0,50,maxColorValue=255),pch=16,
panel.last=abline(h=67,v=1.89, lty=1,lwd=3))
My plot looks like this:
1.) How can I plot the value of the ablines in a simple plot?
2.) How can I scale my plot so that both lines appear in the middle?
to change scale of plot so lines are in the middle change the axes i.e.
x<-1:10
y<-1:10
plot(x,y)
abline(a=1,b=0,v=1)
changed to:
x<-1:10
y<-1:10
plot(x,y,xlim=c(-30,30))
abline(a=1,b=0,v=1)
by "value" I am assuming you mean where the line cuts the x-axis? Something like text? i.e.:
text((0), min(y), "number", pos=2)
if you want the label on the x axis then try:
abline(a=1,b=0,v=1)
axis(1, at=1,labels=1)
to prevent overlap between labels you could remove the zero i.e.:
plot(x,y,xlim=c(-30,30),yaxt="n")
axis(2, at=c(1.77,5,10,15,20,25))
or before you plot extend the margins and add the labels further from the axis
par(mar = c(6.5, 6.5, 6.5, 6.5))
plot(x,y,xlim=c(-30,30))
abline(a=1,b=0,v=1)
axis(2, at=1.77,labels=1.77,mgp = c(10, 2, 0))
Similar in spirit to the answer proposed by #user1317221, here is my suggestion
# generate some fake points
x <- rnorm(100)
y <- rnorm(100)
# positions of the lines
vert = 0.5
horiz = 1.3
To display the lines at the center of the plot, first compute the horizontal and vertical distances between the data points and the lines, then adjust the limits adequately.
# compute the limits, in order for the lines to be centered
# REM we add a small fraction (here 10%) to leave some empty space,
# available to plot the values inside the frame (useful for one the solutions, see below)
xlim = vert + c(-1.1, 1.1) * max(abs(x-vert))
ylim = horiz + c(-1.1, 1.1) * max(abs(y-horiz))
# do the main plotting
plot(x, y, xlim=xlim, ylim=ylim)
abline(h=horiz, v=vert)
Now, you could plot the 'values of the lines', either on the axes (the lineparameter allows you to control for possible overlapping):
mtext(c(vert, horiz), side=c(1,2))
or alternatively within the plotting frame:
text(x=vert, y=ylim[1], labels=vert, adj=c(1.1,1), col='blue')
text(x=xlim[1], y=horiz, labels=horiz, adj=c(0.9,-0.1), col='blue')
HTH
I'm generating numerous plots with xlim and ylim values that I'm calculating on a per-plot basis. I want to put my legend outside the plot area (just above the box around the actual plot), but I can't figure out how to get the maximum y-value of the box around my plot area.
Is there a method for even doing this? I can move the legend where I want it by manually changing the legend() x and y values, but this takes a LONG time for the amount of graphs I'm creating.
Thanks!
-JM
Here's a basic example illustrating what I think you're looking for using one of the code examples from ?legend.
#Construct some data and start the plot
x <- 0:64/64
y <- sin(3*pi*x)
plot(x, y, type="l", col="blue")
points(x, y, pch=21, bg="white")
#Grab the plotting region dimensions
rng <- par("usr")
#Call your legend with plot = FALSE to get its dimensions
lg <- legend(rng[1],rng[2], "sin(c x)", pch=21,
pt.bg="white", lty=1, col = "blue",plot = FALSE)
#Once you have the dimensions in lg, use them to adjust
# the legend position
#Note the use of xpd = NA to allow plotting outside plotting region
legend(rng[1],rng[4] + lg$rect$h, "sin(c x)", pch=21,
pt.bg="white", lty=1, col = "blue",plot = TRUE, xpd = NA)
The command par('usr') will return the coordinates of the bounding box, but you can also use the grconvertX and grconvertY functions. A simple example:
plot(1:10)
par(xpd=NA)
legend(par('usr')[1], par('usr')[4], yjust=0, legend='anything', pch=1)
legend( grconvertX(1, from='npc'), grconvertY(1, from='npc'), yjust=0,
xjust=1, legend='something', lty=1)
The oma, omd, and omi arguments of par() control boundaries and margins of plots - they can be queried using par()$omd (etc). and set (if needed) using par(oma=c()) (where the vector can have up to 4 values - see ?par)