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)):
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'm trying to fit Variance-Gamma distribution to empirical data of 1-minute logarithmic returns. In order to visualize the results I plotted together 2 histograms: empirical and theoretical.
(a is the vector of empirical data)
SP_hist <- hist(a,
col = "lightblue",
freq = FALSE,
breaks = seq(a, max(a), length.out = 141),
border = "white",
main = "",
xlab = "Value",
xlim = c(-0.001, 0.001))
hist(VG_sim_rescaled,
freq = FALSE,
breaks = seq(min(VG_sim_rescaled), max(VG_sim_rescaled), length.out = 141),
xlab = "Value",
main = "",
col = "orange",
add = TRUE)
(empirical histogram-blue, theoretical histogram-orange)
However, after having plotted 2 histograms together, I started wondering about 2 things:
In both histograms I stated, that freq = FALSE. Therefore, the y-axis should be in range (0, 1). In the actual picture values on the y-axis exceed 3,000. How could it happen? How to solve it?
I need to change the bucketing size (the width of the buckets) and the density per unit length of the x-axis. How is it possible to do these tasks?
Thank you for your help.
freq=FALSE means that the area of the entire histogram is normalized to one. As your x-axis has a very small range (about 10^(-4)), the y-values must be quite large to achieve an area (= x times y) of one.
The only way to set the number of bins is by providing a vector of break points to the parameter breaks. Theoretically, this parameter also accepts a single number, but this number is ignored by hist. Thus try the following:
bins <- 6 # number of cells
breaks <- seq(min(x),max(x),(max(x)-min(x))/bins)
hist(x, freq=FALSE, breaks=breaks)
I generate a boxplot with code below:
boxplot(top10threads$affect ~ top10threads$ThreadID[], data = top10threads, xlab = "10 biggest Threads", ylab = "Affect", col=(c("gold","darkgreen")), srt=45)
But as you may notice that some labels in x-axis are missing, so I want to rotate them into 45 degrees. I added srt=45, but it doesn't work.
By setting las=2 can rotate them vertically, but it's not exactly I need.
How could I do that? Thanks.
First, store the output of boxplot() as a object. It contains names of the groups. You can use $names to get them. Then use text() to add labels on the axis. The argument srt works on text().
bp <- boxplot(y ~ x, data = df, col = c("gold", "darkgreen"), xaxt = "n")
tick <- seq_along(bp$names)
axis(1, at = tick, labels = FALSE)
text(tick, par("usr")[3] - 0.3, bp$names, srt = 45, xpd = TRUE)
Data
df <- data.frame(x = sample(100:110, 100, TRUE), y = rnorm(100))
Some test data:
mydata=lapply(1:5,function(i) rnorm(100,mean=i))
names(mydata)=c("first","second","third","fourth","fifth")
First, plot the boxplot with no x-axis:
boxplot(mydata,xaxt="n",xlab="")
Then, we make a function to add textual x-axis labels:
x_axis_labels=function(labels,every_nth=1,...) {
axis(side=1,at=seq_along(labels),labels=F)
text(x=(seq_along(labels))[seq_len(every_nth)==1],
y=par("usr")[3]-0.075*(par("usr")[4]-par("usr")[3]),
labels=labels[seq_len(every_nth)==1],xpd=TRUE,...)
}
# axis() draws the axis with ticks at positions specified by at. Again, we don't plot the labels yet.
# text() plots the labels at positions given by x and y.
# We estimate the y-positions from the values of the y-axis (using par("usr")),
# and specify xpd=TRUE to indicate that we don't want to crop plotting to within the plot area
# Note that we select the [seq_len(every_nth)==1] elements of both the x positions and the labels,
# so we can easily skip labels if there would be too many to cram in otherwise.
# Finally, we leave a ... in the function so we can pass additional arguments to text()
Finally, we call the new function to plot the axis tick labels:
x_axis_labels(labels=names(mydata),every_nth=1,adj=1,srt=45)
Here we take advantage of the ... in the function to pass the rotation/justification parameters: adj=1 specifies to right-justify the text labels, and srt=45 indicates to rotate them by 45 degrees.
I have made my own data set for a student project I'm working on and I am attempting to plot a graph to show employment outcomes, the number employed, in different regions. I am new to Rstudio/data in general and a technophobe! I am struggling to get my Y axis to show the numbers as normal numbers, not exponential notation (if that's what it's called 6e+04 etc?)
Further to this, the X axis is only choosing certain regions to display, more if I expand it. How can I fix this to show all the regions?
Thanks so much in advance for any help!
I have tried using ylim=c(ymin=0, ymax=100000) in the plot. (Info, max value for employed is just below 100000). But this made no change to the plot.
employment.region$Region<- factor(employment.region$Employed, labels=c("North East","North West","Yorkshire","East Midlands","West Midlands","East of England","London","South East","South West","Wales","Scotland"))
plot(employment.region$Region,employment.region$Employed, ylim=c(ymin=0, ymax=100000), frame= FALSE)
AND
plot(employment.region$Employed~employment.region$Region, ylim=c(ymin=0, ymax=100000))
Plot without a y axis, then set the tick marks and the axis labels by hand. This is why yticks and yaxis_labs are defined.
Then plot, with las = 2 to have the axis' annotations perpendicular to the axis.
yticks <- seq(0, 100000, by = 2e4)
yaxis_labs <- formatC(yticks, digits = 6)
old_par <- par(mar = c(7, 4, 4, 2) + 0.1)
plot(employment.region$Region, employment.region$Employed,
ylim=c(ymin=0, ymax=100000), frame= FALSE, las = 2, yaxt = "n")
axis(2, at = yticks, labels = yaxis_labs, las = 2)
par(old_par)
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.