Barplot with 2 variables, 2 y-axis - r

I have the following data
test<-data.frame(group=1:10, var.a=rnorm(n=10,mean=500,sd=20), var.b=runif(10))
I would like a barplot with 2 y axis (one for var.a, one for var.2). Each group (x axis, 1:10) should have 2 bars next to each other, one for var.a and one for var.b.
I cannot use one y-axis because of the difference morder of magnitude of var.a and var.b
Is this possible with base R?
Thank you

To use the graphics package in R, one could create new variables as the values in var.a and var.b converted into proportions of the maximum values in the respective variable:
test <- data.frame(group = 1:10, var.a = rnorm(n = 10, mean = 500, sd = 20),
var.b = runif(10))
funProp <- function(testCol) {
test[, testCol]/max(test[, testCol])
}
test$var.a.prop <- funProp("var.a")
test$var.b.prop <- funProp("var.b")
Then draw the plot using barplot() without the axes:
barplot(t(as.matrix(test[, c("var.a.prop", "var.b.prop")])), beside = TRUE,
yaxt = "n", names.arg = test$group)
Then add the axes on the left and the right using the original value ranges for the labels (the labels argument) and the proportional value ranges to place the labels on the axes (the at argument) (this part is not pretty, but it gets the job done):
axis(2, at = seq(0, max(test$var.a.prop), length.out = 10),
labels = round(seq(0, max(test$var.a), length.out = 10)))
axis(4, at = seq(0, max(test$var.b.prop), length.out = 10),
labels = round(seq(0, max(test$var.b), length.out = 10), 2))
(Sorry for the lack of an image)
EDIT:
To get the axes a bit prettyer,
myLeftAxisLabs <- pretty(seq(0, max(test$var.a), length.out = 10))
myRightAxisLabs <- pretty(seq(0, max(test$var.b), length.out = 10))
myLeftAxisAt <- myLeftAxisLabs/max(test$var.a)
myRightAxisAt <- myRightAxisLabs/max(test$var.b)
barplot(t(as.matrix(test[, c("var.a.prop", "var.b.prop")])),
beside = TRUE, yaxt = "n", names.arg = test$group,
ylim=c(0, max(c(myLeftAxisAt, myRightAxisAt))))
axis(2, at = myLeftAxisAt, labels = myLeftAxisLabs)
axis(4, at = myRightAxisAt, labels = myRightAxisLabs)

Related

"col" argument in plot function not working when a factor value is used for x - axis

I am doing quarterly analysis, for which I want to plot a graph. To maintain continuity on x axis I have turned quarters into factors. But then when I am using plot function and trying to color it red, the col argument is not working.
An example:
quarterly_analysis <- data.frame(Quarter = as.factor(c(2020.1,2020.2,2020.3,2020.4,2021.1,2021.2,2021.3,2021.4)),
AvgDefault = as.numeric(c(0.24,0.27,0.17,0.35,0.32,0.42,0.38,0.40)))
plot(quarterly_analysis, col="red")
But I am getting the graph in black color as shown below:
Converting it to a factor is not ideal to plot unless you have multiple values for each factor - it tries to plot a box plot-style plot. For example, with 10 observations in the same factor, the col = "red" color shows up as the fill:
set.seed(123)
fact_example <- data.frame(factvar = as.factor(rep(LETTERS[1:3], 10)),
numvar = runif(30))
plot(fact_example$factvar, fact_example$numvar,
col = "red")
With only one observation for each factor, this is not ideal because it is just showing you the line that the box plot would make.
You could use border = "red:
plot(quarterly_analysis$Quarter,
quarterly_analysis$AvgDefault, border="red")
Or if you want more flexibility, you can plot it numerically and do a little tweaking for more control (i.e., can change the pch, or make it a line graph):
# make numeric x values to plot
x_vals <- as.numeric(substr(quarterly_analysis$Quarter,1,4)) + rep(seq(0, 1, length.out = 4))
par(mfrow=c(1,3))
plot(x_vals,
quarterly_analysis$AvgDefault, col="red",
pch = 7, main = "Square Symbol", axes = FALSE)
axis(1, at = x_vals,
labels = quarterly_analysis$Quarter)
axis(2)
plot(x_vals,
quarterly_analysis$AvgDefault, col="red",
type = "l", main = "Line graph", axes = FALSE)
axis(1, at = x_vals,
labels = quarterly_analysis$Quarter)
axis(2)
plot(x_vals,
quarterly_analysis$AvgDefault, col="red",
type = "b", pch = 7, main = "Both", axes = FALSE)
axis(1, at = x_vals,
labels = quarterly_analysis$Quarter)
axis(2)
Data
set.seed(123)
quarterly_analysis <- data.frame(Quarter = as.factor(paste0(2019:2022,
rep(c(".1", ".2", ".3", ".4"),
each = 4))),
AvgDefault = runif(16))
quarterly_analysis <- quarterly_analysis[order(quarterly_analysis$Quarter),]

How to specify breaks for y axis in R plot

I have created the following fanchart using the fanplot package. I'm trying to add axis ticks and labels to the y axis, however it's only giving me the decimals and not the full number. Looking for a solution to display the full number (e.g 4.59 and 4.61) on the y axis
I am also unsure of how to specify the breaks and number of decimal points for the labels on the y-axis using plot(). I know doing all of this in ggplot2 it would look something like this scale_y_continuous(breaks = seq(min(data.ts$Index),max(data.ts$Index),by=0.02)) . Any ideas on how to specify the breaks in the y axis as well as the number of decimal points using the base plot() feature in R?
Here is a reproductible of my dataset data.ts
structure(c(4.6049904235401, 4.60711076016453, 4.60980084146652,
4.61025389170935, 4.60544515681515, 4.60889021700954, 4.60983993107244,
4.61091608826696, 4.61138799159174, 4.61294431148318, 4.61167545843765,
4.61208284263432, 4.61421991328081, 4.61530485425155, 4.61471465043043,
4.6155992084451, 4.61195799200607, 4.61178486640435, 4.61037927954796,
4.60744590947049, 4.59979957741728, 4.59948551500254, 4.60078678080182,
4.60556092645471, 4.60934962087565, 4.60981147563749, 4.61060477704678,
4.61158365084251, 4.60963435263623, 4.61018215733317, 4.61209710959768,
4.61231368335184, 4.61071363571141, 4.61019496497916, 4.60948652606191,
4.61068813487859, 4.6084092003352, 4.60972706132393, 4.60866915174087,
4.61192565195909, 4.60878767339377, 4.61341471281265, 4.61015272152397,
4.6093479714315, 4.60750965935653, 4.60768790690338, 4.60676463096309,
4.60746490411374, 4.60885670935448, 4.60686846708382, 4.60688947889575,
4.60867708110485, 4.60448791268212, 4.60387348166032, 4.60569806689426,
4.6069320880709, 4.6087143894128, 4.61059688801283, 4.61065399116698,
4.61071421014339), .Tsp = c(2004, 2018.75, 4), class = "ts")
and here is a reproductible of the code I'm using
# # Install and Load Packages
## pacman::p_load(forecast,fanplot,tidyverse,tsbox,lubridate,readxl)
# Create an ARIMA Model using the auto.arima function
model <- auto.arima(data.ts)
# Simulate forecasts for 4 quarters (1 year) ahead
forecasts <- simulate(model, n=4)
# Create a data frame with the parameters needed for the uncertainty forecast
table <- ts_df(forecasts) %>%
rename(mode=value) %>%
mutate(time0 = rep(2019,4)) %>%
mutate(uncertainty = sd(mode)) %>%
mutate(skew = rep(0,4))
y0 <- 2019
k <- nrow(table)
# Set Percentiles
p <- seq(0.05, 0.95, 0.05)
p <- c(0.01, p, 0.99)
# Simulate a qsplitnorm distribution
fsval <- matrix(NA, nrow = length(p), ncol = k)
for (i in 1:k)
fsval[, i] <- qsplitnorm(p, mode = table$mode[i],
sd = table$uncertainty[i],
skew = table$skew[i])
# Create Plot
plot(data.ts, type = "l", col = "#75002B", lwd = 4,
xlim = c(y0 - 2,y0 + 0.75), ylim = range(fsval, data.ts),
xaxt = "n", yaxt = "n", ylab = "",xlab='',
main = '')
title(ylab = 'Log AFSI',main = 'Four-Quarter Ahead Forecast Fan - AFSI',
xlab = 'Date')
rect(y0 - 0.25, par("usr")[3] - 1, y0 + 2, par("usr")[4] + 1,
border = "gray90", col = "gray90")
fan(data = fsval, data.type = "values", probs = p,
start = y0, frequency = 4,
anchor = data.ts[time(data.ts) == y0 - .25],
fan.col = colorRampPalette(c("#75002B", "pink")),
ln = NULL, rlab = NULL)
# Add axis labels and ticks
axis(1, at = y0-2:y0 + 2, tcl = 0.5)
axis(1, at = seq(y0-2, y0 + 2, 0.25), labels = FALSE, tcl = 0.25)
abline(v = y0 - 0.25, lty = 1)
abline(v = y0 + 0.75, lty = 2)
axis(2, at = range(fsval, data.ts), las = 2, tcl = 0.5)
range(blah) will only return two values (the minimum and maximum). The at parameter of axis() requires a sequence of points at which you require axis labels. Hence, these are the only two y values you have on your plot. Take a look at using pretty(blah) or seq(min(blah), max(blah), length.out = 10).
The suggestions of #Feakster are worth looking at, but the problem here is that the y-axis margin isn't wide enough. You could do either of two things. You could round the labels so they fit within the margins, for example you could replace this
axis(2, at = range(fsval, data.ts), las = 2, tcl = 0.5)
with this
axis(2, at = range(fsval, data.ts),
labels = sprintf("%.3f", range(fsval, data.ts)), las = 2, tcl = 0.5)
Or, alternatively you could increase the y-axis margin before you make the plot by specifying:
par(mar=c(5,5,4,2)+.1)
plot(data.ts, type = "l", col = "#75002B", lwd = 4,
xlim = c(y0 - 2,y0 + 0.75), ylim = range(fsval, data.ts),
xaxt = "n", yaxt = "n", ylab = "",xlab='',
main = '')
Then everything below that should work. The mar element of par sets the number of lines printed in the margin of each axis. The default is c(5,4,4,2).

formatting the x-axis exponential plot in R as a^x?

I have generated this plot in R with some strange numbers format in the x-axis:
enter image description here
I want to have in the x-axis the numbers in the format (ax) as 2^6, 6^6, 10^6. this would simplify the x-axis to get data in all points. Please do you have any suggestions?
Here my code :
data=read.csv("my_file.csv",row.names = 1)
plot(genes~Prot,cex=1.5,data, function(x) 10^x, xlab="Proteome
size(codons)",ylim=c(0,30), ylab="Genes in pathway")
abline(lm(prot~genes,data),lty=2, lwd=3,col="black")
Use xaxt = 'n' as an argument to plot to turn off the x-axis labelling. Then use the Axis function to set tick marks and label as required.
# Generating some data
power <- seq(1, 6, length.out = 20)
Prot = 10^power
genes <- runif(20, min = 5, max = 30)
# plotting
plot(x= Prot, y= genes, cex=1.5, xlab="Proteome size(codons)", ylab="Genes in pathway", xaxt = 'n', log = 'xy')
Axis(at = c(2^6, 6^6, 10^6), side = 1, labels = c('2^6', '6^6', '10^6'), las = 1)

Put one line chart and bar chart in one plot in R (Not ggplot)?

how to
Combine a bar chart and line in single plot in R (from different data sources)?
Say I have two data sources as:
barData<-c(0.1,0.2,0.3,0.4) #In percentage
lineData<-c(100,22,534,52,900)
Note that they may not be in the same scale.
Can I plot both barData and LineData in one plot and make them good looking ?
I cant use ggplot in this case so this is not a duplicated question..
Something like the following:
Maybe this helps as a starting point:
par(mar = rep(4, 4))
barData<-c(0.1,0.2,0.3,0.4) * 100
y <- lineData<-c(100,22,534,900);
x <- barplot(barData,
axes = FALSE,
col = "blue",
xlab = "",
ylab = "",
ylim = c(0, 100) )[, 1]
axis(1, at = x, labels = c("Julia", "Pat", "Max", "Norman"))
ats <- c(seq(0, 100, 15), 100); axis(4, at = ats, labels = paste0(ats, "%"), las = 2)
axis(3, at = x, labels = NA)
par(new = TRUE)
plot(x = x, y = y, type = "b", col = "red", axes = FALSE, xlab = "", ylab = "")
axis(2, at = c(pretty(lineData), max(lineData)), las = 2)
mtext(text="Lines of code by Programmer", side = 3, line = 1)
box()

Segments on the plot

I want to draw several (lets say - 5 for now) segments on my plot. I've tried segments() function but it draws only two segments out of 5 given coordinates. Here is the code :
begs <- c(34573131,35072050,35471145, 35746065,36504818)
ends <- c(34887083,35139735,35557793,35789178,36950091)
step <- 820000
plot(1, xlim = c(33900000,38000000), axes = F, xlab="Position")
axis(1, at = seq(33900000,38000000, by=step), labels=format(seq(33900000,38000000, by=step)/1e6, scientific=F, digits=3))
axis(4, at = seq(0,2,length.out = 5), labels = seq(0,2,length.out = 5) )
segments(x0 = begs, x1 = ends, y0 = c(0.1, 0.5 , 0.9 ,1.4, 1.9))
and the plot looks like that :
Your first call to plot() causes R to calculate the x and y range. Thus if your data in this first call is not representative of the range, you need to specify the range manually.
Concretely, add ylim=c(...) to your plot() call:
Try this:
min <- 33900000
max <- 38000000
plot(1, xlim = c(min, max), ylim=c(0, 2),
axes = FALSE, xlab="Position", ylab="", type="n")
axis(1, at = seq(min, max, by=step), labels=format(seq(min, max, by=step)/1e6,
scientific=F, digits=3))
axis(4, at = seq(0,2,length.out = 5), labels = seq(0,2,length.out = 5) )
segments(x0 = begs, x1 = ends, y0 = c(0.1, 0.5 , 0.9 ,1.4, 1.9))

Resources