I plotted a histogram using Lattice
histogram(~Time |factor(Bila), data=flexi2, xlim= c(5, 15), ylim=c(0, 57),
scales=list(x=list(at=seq(5,15,1))), xlab="Time",
subset=(Bila%in% c("")))`
The bins I get do not match the exact hours, whereas I would like the bin to start at the exact hour, for example, 6,7 etc. I use lattice since I want conditional histograms. I have extracted here just one histogram to illustrate.
UPDATE:
Here is a reproducible example (I hope) as was requested. As can be seen 0 for example is not at the limit of bins.
x<-rnorm(1000)
histogram(~x)
This happens because you specified the x axis scale with scales = list(x = list(at = 5:15)), but you didn't actually change the breakpoints. It happens in the default case as well: the default axis labels are integers, but the default breakpoints are determined programmatically and are not necessarily integers unless you have integer-valued data.
An easy fix would be to specify your own breaks in the breaks argument:
histogram(~Time |factor(Bila), data=flexi2, subset=(Bila %in% c("")),
xlim= c(5, 15), ylim=c(0, 57),
breaks = 5:15,
scales = list(x = list(at = 5:15)),
xlab="Time")
And an example:
library(lattice)
x <- rnorm(1000)
x[abs(x) > 3] <- 3
x_breaks <- c(-3, -1.5, 0, 1.5, 3)
histogram(~ x,
title = "Defaults")
histogram(~ x, breaks = x_breaks,
title = "Custom bins, default tickmarks")
histogram(~ x, scales = list(x = list(at = x_breaks)),
title = "Custom tickmarks, default bins")
histogram(~ x, breaks = x_breaks, scales = list(x = list(at = x_breaks)),
title = "Custom tickmarks, custom bins")
Related
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),]
I want to create a figure where for various reasons I need to specify the axis labels myself. But when I specify my labels (some have one digit, some two digits) R suppresses every other two-digit label because it decides there isn't enough room to show them all, but it leaves all of the one-digit labels, leaving the axis looking lopsided.
Is there a way to suppress labels consistently across the whole axis, based on whether any of them need to be skipped? Note: I have a lot of plots with varying scales, so I was looking for something I could use for all of them - I don't want to render all the labels for every plot, or to skip every other label in every plot. Suppressing labels will be desirable for some plots and not for others. I just want to skip every other label consistently, if that's what R chooses to do for the particular plot.
(Here is an example figure of what I mean. What I want is for the "6%" label to also be suppressed in the x axis.)
Example code:
library(labeling)
df <- data.frame("estimate" = c(9.81, 14.29, 12.94),
"lower" = c(4.54, 6.25, 5.12),
"upper" = c(12.85, 20.12, 15.84))
ticks <- extended(min(df$lower), max(df$upper), m = 5, only.loose = TRUE,
Q=c(2, 5, 10))
png("examplePlot.png", width = 1200, height = 900, pointsize = 10, res = 300)
bars <- barplot(df$estimate, horiz = TRUE, col = "white", border = NA,
xlim = c(min(ticks), max(ticks)), xaxt = "n", main = "Example")
arrows(df$lower, bars, df$upper, bars, code = 3, angle = 90, length = 0.03)
points(df$estimate, bars, pch = 20)
tickLabels <- paste(ticks, "%", sep = "")
axis(1, at=ticks, labels = tickLabels, cex.axis=1)
axis(2, at = bars, labels = c("c", "b", "a"), lwd = 0, las = 2)
dev.off()
This depends on the size of the plot, so you'll have to plot each label separately:
axis(1, lwd.ticks = 1, labels = FALSE, at = ticks) # plot line and ticks
i <- seq(1,length(ticks),2) # which labels to plot
for(ii in i)
axis(1, at = ticks[ii], labels = tickLabels[ii], cex.axis = 1, lwd = 0)
This question already has answers here:
How can I plot with 2 different y-axes?
(6 answers)
Closed 6 years ago.
i'm having troubles in a multi axis barplot. I have an X,Y axis with bars and dots in the same graph. The point is that I have to shown both of them in different scales
While I can shown both (bars and dots) correctly, the problem comes when I try to set different scales in left and right axis. I dont know how to change the aditional axis scale, and how to bind the red dots to the right axis, and the bars to the left one.
This is my code and what I get:
labels <- value
mp <- barplot(height = churn, main = title, ylab = "% churn", space = 0, ylim = c(0,5))
text(mp, par("usr")[3], labels = labels, srt = 45, adj = c(1.1,1.1), xpd = TRUE, cex=.9)
# Population dots
points(popul, col="red", bg="red", pch=21, cex=1.5)
# Churn Mean
media <- mean(churn)
abline(h=media, col = "black", lty=2)
# Population scale
axis(side = 4, col= "red")
ylim= c(0,50)
ylim= c(0,5)
What I want is to have left(grey) axis at ylim=c(0,5) with the bars bound to that axis. And the right(red) axis at ylim=c(0,50) with the dots bound to that axis...
The goal is to represent bars and points in the same graph with diferent axis.
Hope I explained myself succesfully.
Thanks for your assistance!
Here is a toy example. The only "trick" is to store the x locations of the bar centers and the limits of the x axis when creating the barplot, so that you can overlay a plot with the same x axis and add your points over the centers of the bars. The xaxs = "i" in the call to plot.window indicates to use the exact values given rather than expanding by a constant (the default behavior).
set.seed(1234)
dat1 <- sample(10, 5)
dat2 <- sample(50, 5)
par(mar = c(2, 4, 2, 4))
cntrs <- barplot(dat1)
xlim0 <- par()$usr[1:2]
par(new = TRUE)
plot.new()
plot.window(xlim = xlim0, ylim = c(0, 50), xaxs = "i")
points(dat2 ~ cntrs, col = "darkred")
axis(side = 4, col = "darkred")
I have created a plot in R and my own custom x and y axes. I would like the x axis to be displayed in a reverse order (1-0 by -.02). I have read numerous posts and threads that suggest using xlim and reverse range but I just can't seem to make it work. Once plotted I am also converting the axes labels to percentages by multiplying by 100 (as you will see in the code). Here is what I have so far;
plot(roc.val, xlab = "Specificity (%)", ylab = "Sensitivity (%)", axes = FALSE)
axis(2, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
axis(1, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
How can I reverse the x axis scale so that the values begin at 100 and end at 0 with increments of 20?
I think this creates a plot in which the y-axis is in reverse order:
x <- seq(-4, 4, length = 10)
y <- exp(x) / (1 + exp(x))
plot(x,y, ylim = rev(range(y)))
This removes the axis values:
x <- seq(-4, 4, length = 10)
y <- exp(x) / (1 + exp(x))
plot(x,y, ylim = rev(range(y)), labels = FALSE)
I guess you can assign the axis values you want then with a variation of your lines:
axis(2, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
axis(1, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
df <- data.frame(x=seq(0,1, length.out=50), y=seq(0, 1, length.out=50))
plot(df)
df$x1 <- (max(df$x) - df$x)/ (max(df$x) - min(df$x))
plot(df$x1, df$y, axes=F, xlab = "Specificity (%)", ylab = "Sensitivity (%)")
axis(2, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
axis(1, at = seq(0,1,by=.2), labels = paste(100*seq(1,0, by=-.2)), tick = TRUE)
Adapting Mark Miller's answer to solve a similar problem (I found this topic by looking for the solution) and I found a variation of his solution in https://tolstoy.newcastle.edu.au/R/help/05/03/0342.html.
Basically if you want to reverse the X-axis values in the plot, instead of using ylim=rev(range(y)), you can use xlim=rev(c(-4,4)).
x <- seq(-4, 4, length = 10)
y <- exp(x) / (1 + exp(x))
par(mfrow=c(1,2))
plot(x, y, ylim=range(y), xlim=c(-4, 4))
plot(x, y, ylim=range(y), xlim=rev(c(-4, 4)))
plot1
And if you want to keep the x-axis values in the true order, you can use this:
par(mfrow=c(1,1))
plot(x, y, ylim=range(y), xlim=c(-4, 4), axes=FALSE)
par(new=TRUE)
plot(-100, -100, ylim=range(y), xlim=c(-4, 4), axes=FALSE, xlab="", ylab="", main="")
axis(1, at = seq(-4,4,by=1), labels = seq(-4,4,by=1), tick = TRUE)
axis(2, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
plot2
I'm posting this solution because I needed something very straightforward to solve my problem. And the solution for it needed the plot with the X-axis value in the correct order (and not reversed).
First, check out the ggplot2 library for making beautiful and extendable graphics. It is part of the Tidyverse approach to R and a gamechanger if you have not been exposed to it.
For example, to solve your issue using ggplot, you simply add the term scale_x_reverse() to your graphic.
See: http://ggplot.yhathq.com/docs/scale_x_reverse.html
I'm trying to create a figure similar to the one below (taken from Ro, Russell, & Lavie, 2001). In their graph, they are plotting bars for the errors (i.e., accuracy) within the reaction time bars. Basically, what I am looking for is a way to plot bars within bars.
I know there are several challenges with creating a graph like this. First, Hadley points out that it is not possible to create a graph with two scales in ggplot2 because those graphs are fundamentally flawed (see Plot with 2 y axes, one y axis on the left, and another y axis on the right)
Nonetheless, the graph with superimposed bars seems to solve this dual sclaing problem, and I'm trying to figure out a way to create it in R. Any help would be appreciated.
It's fairly easy in base R, by using par(new = T) to add to an existing graph
set.seed(54321) # for reproducibility
data.1 <- sample(1000:2000, 10)
data.2 <- sample(seq(0, 5, 0.1), 10)
# Use xpd = F to avoid plotting the bars below the axis
barplot(data.1, las = 1, col = "black", ylim = c(500, 3000), xpd = F)
par(new = T)
# Plot the new data with a different ylim, but don't plot the axis
barplot(data.2, las = 1, col = "white", ylim = c(0, 30), yaxt = "n")
# Add the axis on the right
axis(4, las = 1)
It is pretty easy to make the bars in ggplot. Here is some example code. No two y-axes though (although look here for a way to do that too).
library(ggplot2)
data.1 <- sample(1000:2000, 10)
data.2 <- sample(500:1000, 10)
library(ggplot2)
ggplot(mapping = aes(x, y)) +
geom_bar(data = data.frame(x = 1:10, y = data.1), width = 0.8, stat = 'identity') +
geom_bar(data = data.frame(x = 1:10, y = data.2), width = 0.4, stat = 'identity', fill = 'white') +
theme_classic() + scale_y_continuous(expand = c(0, 0))