I have a horizontal barplot, with zero in the middle of the x-axis and would like the name for each bar to appear on the same side as the bar itself. The code I am using is:
abun<-data$av.slope
species<-data$Species
cols <- c("blue", "red")[(abun > 0)+1]
barplot(abun, main="Predicted change in abundance", horiz=TRUE,
xlim=c(-0.04,0.08), col=cols, names.arg=species, las=1, cex.names=0.6)
I have tried creating two separate axes and the names do appear on the desired side for each bar, but are not level with the appropriate bar. I will try and upload an image of the barplot, am still very new to R, apologies if I am missing something basic!
barplot1- names in correct position but all on one axis
barplot2- names on both sides of plot but not in line with appropriate bar
We can accomplish this using mtext:
generate data
Since you didn't include your data in the question I generated my own dummy data set. If you post a dput of your data, we could adapt this solution to your data.
set.seed(123)
df1 <- data.frame(x = rnorm(20),
y = LETTERS[1:20])
df1$colour <- ifelse(df1$x < 0, 'blue', 'red')
make plot
bp <- barplot(df1$x, col = df1$colour, horiz = T)
mtext(side = ifelse(df1$x < 0, 2, 4),
text = df1$y,
las = 1,
at = bp,
line = 1)
Related
I have a problem labelling my matplot x-axis row. So I have 1388 instances, but I want my X-axis to a custom labeling in the form of a sequence in dates.
My R code looks like this:
Dates <- seq(as.Date("2004/01/29"), as.Date("2009/07/31"), by = "quarter")
matplot(seq(1388), t(Alldata[1, ]), type = "l",
lwd = 1, lty = 1, col = 1:10, xlab = "Dates", ylab = "Strike",
main = paste("TEST"), xaxt='n')
axis(side = 1:23, at=1, labels = paste(Dates, 1:23))
Can anybody help me get the Dates into the x-axis?
I have tried using same method as this: Change axis labels with matplot in R
but it doesn't work.
AllData is from an excel file in which the first number of rows looks like this:
I think you have confused the way the function axis works. In answering below I will generate a random matrix to replace your Alldata which I don't have access to
Alldata <- t(as.matrix(rnorm(23)))
We can generate the plot again:
matplot(seq(23), Alldata[1, ], type = "l",
lwd = 1, lty = 1, col = 1:10, xlab = "Dates",
ylab = "Strike", main = paste("TEST"), xaxt='n')
Now, its import to know what the arguments to axis are. First
side this is literally the side of the the rectangle on which the plot is drawn. It is one of the numbers 1, 2, 3, 4 corresponding to bottom, left, top, right, respectively.
You want the axis to be on the bottom so we set this to 1.
Next, the at argument, is for where the tick marks should be drawn. So if you have 10 points on your line, and you set this value to 1:10 it will draw a tick mark at each point on the axis. If you set it to c(2,4,6,8,10) it will draw a mark at every second point on the axis. In your case you've set it to 1, which would draw only one tick. Although since the side was set to 1:23 none showed up.
labels This argument will label the ticks which are drawn. Ideally it should be a vector the same length as the at value. You can make sure that they are the same length by creating an index variable and using this as the at variable and to index the labels.
This gets us to:
index <- c(1,7,14,21)
axis(side = 1, at = index, labels = paste(Dates, 1:23)[index])
I think having a full range of dates would look cluttered. But you can drop the index and choose the below if you prefer:
axis(side = 1, at = 1:23, labels = paste(Dates, 1:23))
I asked a question before, but now I would like to know how do I put the labels above the bars.
post old: how to create a frequency histogram with predefined non-uniform intervals?
dataframe <- c (1,1.2,40,1000,36.66,400.55,100,99,2,1500,333.45,25,125.66,141,5,87,123.2,61,93,85,40,205,208.9)
Upatdate
Update
Following the guidance of the colleague I am updating the question.
I have a data base and I would like to calculate the frequency that a given value of that base appears within a pre-defined range, for example: 0-50, 50-150, 150-500, 500-2000.
in the post(how to create a frequency histogram with predefined non-uniform intervals?) I managed to do this, but I don't know how to add the labels above the bars. I Tried:
barplort (data, labels = labels), but it didn't work.
I used barplot because the post recommended me, but if it is possible to do it using ggplot, it would be good too.
Based on the answer to your first question, here is one way to add a text() element to your Base R plot, that serves as a label for each one of your bars (assuming you want to double-up the information that is already on the x axis).
data <- c(1,1.2,40,1000,36.66,400.55,100,99,2,1500,333.45,25,125.66,141,5,87,123.2,61,93,85,40,205,208.9)
# Cut your data into categories using your breaks
data <- cut(data,
breaks = c(0, 50, 150, 500, 2000),
labels = c('0-50', '50-150', '150-500', '500-2000'))
# Make a data table (i.e. a frequency count)
data <- table(data)
# Plot with `barplot`, making enough space for the labels
p <- barplot(data, ylim = c(0, max(data) + 1))
# Add the labels with some offset to be above the bar
text(x = p, y = data + 0.5, labels = names(data))
If it is the y values that you are after, you can change what you pass to the labels argument:
p <- barplot(data, ylim = c(0, max(data) + 1))
text(x = p, y = data + 0.5, labels = data)
Created on 2020-12-11 by the reprex package (v0.3.0)
I was wondering if it's possible to get a two sided barplot (e.g. Two sided bar plot ordered by date) that shows above Data A and below Data B of each X-Value.
Data A would be for example the age of a person and Data B the size of the same person. The problem with this and the main difference to the examples above: A and B have obviously totally different units/ylims.
Example:
X = c("Anna","Manuel","Laura","Jeanne") # Name of the Person
A = c(12,18,22,10) # Age in years
B = c(112,186,165,120) # Size in cm
Any ideas how to solve this? I don't mind a horizontal or a vertical solution.
Thank you very much!
Here's code that gets you a solid draft of what I think you want using barplot from base R. I'm just making one series negative for the plotting, then manually setting the labels in axis to reference the original (positive) values. You have to make a choice about how to scale the two series so the comparison is still informative. I did that here by dividing height in cm by 10, which produces a range similar to the range for years.
# plot the first series, but manually set the range of the y-axis to set up the
# plotting of the other series. Set axes = FALSE so you can get the y-axis
# with labels you want in a later step.
barplot(A, ylim = c(-25, 25), axes = FALSE)
# plot the second series, making whatever transformations you need as you go. Use
# add = TRUE to add it to the first plot; use names.arg to get X as labels; and
# repeat axes = FALSE so you don't get an axis here, either.
barplot(-B/10, add = TRUE, names.arg = X, axes = FALSE)
# add a line for the x-axis if you want one
abline(h = 0)
# now add a y-axis with labels that makes sense. I set lwd = 0 so you just
# get the labels, no line.
axis(2, lwd = 0, tick = FALSE, at = seq(-20,20,5),
labels = c(rev(seq(0,200,50)), seq(5,20,5)), las = 2)
# now add y-axis labels
mtext("age (years)", 2, line = 3, at = 12.5)
mtext("height (cm)", 2, line = 3, at = -12.5)
Result with par(mai = c(0.5, 1, 0.25, 0.25)):
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.
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.