I am trying to draw a barplot in R
I have 2 vectors
x <- c(1,2,3,4)
y <- c(200,400,4000,255)
A <- rbind(x,y) # to make it into a matrix
barplot(A, ylim= c(0,5000))
I want to put at the base of each plot 1,2,3,4 on the x axis.
How can I do that
Thanks
barplot(A, ylim= c(0,5000),names.arg=1:4)
This is how you do it.
My suggestion is that you should check the help manual/doc for each function carefully. R graphic functions usually have lots of arguments for various purposes.
Function "barplot" returns the x-axis value where each bar is centred. We can use these values as a reference to add legend on top of each bar, or any where else (but less straightforward).
To add on the top
x.axis <-barplot(A, ylim= c(0,5000),names.arg=1:4)
text(x.axis, y, adj = c(0.5, 0)) ## you have defined "y"
Related
I am working in R and I have to make many boxplots. This is a visualization of group differences. I want to relabel the x-axis to only have one title instead of five (one for each subplot). My biggest problem is that I also want the y-axis of all the subplots to have different labels.
This is what I tried so far:
par(mfrow=c(1,5))
lapply(NEW8[,c("gawayf", "humf", "sgamesf", "swtoyf", "kissf")],
function(x) boxplot(x ~ NEW8$PAPA_p4_adhd,col=rainbow(2),
names=c("CN","ADHD"),
ylab=c("gawayf", "humf", "sgamesf", "swtoyf", "kissf")))
All the y-labels are added to each subplots so each subplots has 5 lines of y-axis labels (gawayf, humf, sgamef, swtoyf, kissf), and each plot says what data was used to create the boxplot (PAPA_P4_ADHD).
I want each plots to only have the corresponding y-axis label and the x-axis to have 1 label for all five plots.
This is my current output:
Thank you very much
Instead of lapply try mapply - that will allow to pass different argument to each function call:
par(mfrow=c(1,5))
myBox <- function(x, y, ...) boxplot(x ~ y, col=rainbow(2), names=c("CN", "ADHA"), ...)
mapply(myBox,
x = NEW8[,c("gawayf", "humf", "sgamesf", "swtoyf", "kissf")],
y = list(NEW8$PAPA_p4_adhd), # we make this a list so it has length(1)
ylab = c("gawayf", "humf", "sgamesf", "swtoyf", "kissf"),
xlab = "" # empty x-lab
)
For x-lab you will have to do a trick - start a new empty plot that overlays all of the plots, and only add x-axis:
par(fig=c(0,1,0,1), oma=c(0,0,0,0), mar=par("mar"), new=TRUE)
plot.new()
title(xlab="my x-axis")
NOTE: I didn't try to run this code myself, if anything here doesn't work - please leave a comment and will try to address it.
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)
Let say i have a data like this
M<- matrix(rnorm(20),20,5)
x <- as.matrix(sort(runif(20, 5.0, 7.5)))
The M has 5 columns with the same values which I want to plot it but I don't want to plot them on each other. I want to show them with a space. What I do is like below
plot(x, M[,1], ylim=range(M), ann=FALSE, axes=T,type="l")
Colm <- 2:ncol(M)
lapply(seq_along(Colm),function(i){
lines(x, M[,i], col=Colm[i])
})
Is there any way to make a distance between each line in plot ?
You can add a small change to each y value to shift each line slightly.
set.seed(595)
M <- matrix(rnorm(20),20,5)
x <- as.matrix(sort(runif(20, 5.0, 7.5)))
plot(NA, ylim=range(M), xlim=range(x), ann=FALSE, axes=T, type="l")
# Amount by which to shift each y value
eps = seq(-0.1, 0.1, length.out=ncol(M))
lapply(1:ncol(M), function(i){
lines(x, M[,i] + eps[i], col=i)
})
UPDATE: In answer to your comment, I think the following is probably what's happening: In your sample code, x is a matrix, which behaves essentially the same as a vector when the matrix has only one column. Thus, x will return a data vector, so you can just use the object x directly in the lines function. However, if you're importing x as a data frame (for example, using x=read.table("x.txt", header=TRUE), then you need to use lines(x[,1], M[,i] + eps[i], col=i) in your code in order to get the vector of data in the first column of the data frame x.
If you use ggplot you can do this easily using the alpha command as indicated in this post:
Overlapping Lines in ggplot2
and you could also jitter the lines using code from this post..
How to jitter lines in ggplot2
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)
While plotting histogarm, scatterplots and other plots with axes scaled to logarithmic scale in R, how is it possible to use labels such as 10^-1 10^0 10^1 10^2 10^3 and so on instead of the axes showing just -1, 0, 1, 2, 3 etc. What parameters should be added to the commands such as hist(), plot() etc?
Apart from the solution of ggplot2 (see gsk3's comment), I would like to add that this happens automatically in plot() as well when using the correct arguments, eg :
x <- 1:10
y <- exp(1:10)
plot(x,y,log="y")
You can use the parameter log="x" for the X axis, or log="xy" for both.
If you want to format the numbers, or you have the data in log format, you can do a workaround using axis(). Some interesting functions :
axTicks(x) gives you the location of the ticks on the X-axis (x=1) or Y-axis (x=2)
bquote() converts expressions to language, but can replace a variable with its value. More information on bquote() in the question Latex and variables in plot label in R? .
as.expression() makes the language object coming from bquote() an expression. This allows axis() to do the formatting as explained in ?plotmath. It can't do so with language objects.
An example for nice formatting :
x <- y <- 1:10
plot(x,y,yaxt="n")
aty <- axTicks(2)
labels <- sapply(aty,function(i)
as.expression(bquote(10^ .(i)))
)
axis(2,at=aty,labels=labels)
Which gives
Here is a different way to draw this type of axis:
plot(NA, xlim=c(0,10), ylim=c(1, 10^4), xlab="x", ylab="y", log="y", yaxt="n")
at.y <- outer(1:9, 10^(0:4))
lab.y <- ifelse(log10(at.y) %% 1 == 0, at.y, NA)
axis(2, at=at.y, labels=lab.y, las=1)
EDIT: This is also solved in latticeExtra with scale.components
In ggplot2 you just can add a
... +
scale_x_log10() +
scale_y_log10(limits = c(1e-4,1), breaks=c(1e-4,1e-3,1e-2,0.1,1)) + ...
to scale your axis, Label them and add custom breaks.