Mixed Scale on a Ggplot

Mixed scale on a ggplot

You can create your own scale, see (1,2) for other examples. Here is an example for your particular discontinuous function.

library(scales)
library(ggplot2)

MixLogF <- function(x){
if(x < 0.05){r <- log(x) - log(0.05) + 0.05}
else {r <- x}
return(r)
}
MixLogV <- Vectorize(MixLogF)
InvMixLogF <- function(x){
if(x < 0.05){r <- exp(x - 0.05 + log(0.05))}
else {r <- x}
return(r)
}
InvMixLogV <- Vectorize(InvMixLogF)
MixLogV_trans <- function() trans_new("MixLogV",MixLogV,InvMixLogV,domain = c(0.001, Inf))

y <- (1:100)/100
x <- MixLogV(y)
ExpDat <- data.frame(x,y)
orig <- ggplot(data=ExpDat, aes(x=y,y=y)) + geom_point()
orig
orig + scale_x_continuous(trans="MixLogV", limits=c(0.01, 1), breaks=c(0.01,0.02,0.03,0.04,0.05,0.30,0.80))

Sample Image

Agree with eipi10, use with care - could be misleading.


For labeling purposes, it may be easier to see the effects the function has on the scale by having equal breaks in the plot space. The example below shows that the upper part is quite squished - you can't have a p-value over 1, which when breaking at 0.05 is the same distance away as exp(log(0.05) - 0.95) ~ 0.02.

#For nice even breaks
blog <- c(0.01,0.02,0.03,0.04)
blin <- 0.05 + log(0.05) - log(rev(blog))
orig + scale_x_continuous(trans="MixLogV", limits=c(0.01, blin[4]),
breaks=c(blog,0.05,blin), labels = format(c(blog,0.05,blin),digits=2,scientific = FALSE))

Sample Image

How to set different y-axis scale in a facet_grid with ggplot?

Here is the answer

#Plot absolute values
p1 <- ggplot(C_Em_df[C_Em_df$Type=="Sum",], aes(x = Driver, y = Value, fill = Period, width = .85)) +
geom_bar(position = "dodge", stat = "identity") +
labs(x = "", y = "Carbon emission (T/Year)") +
theme(axis.text = element_text(size = 16),
axis.title = element_text(size = 20),
legend.title = element_text(size = 20, face = 'bold'),
legend.text= element_text(size=20),
axis.line = element_line(colour = "black"))+
scale_fill_grey("Period") +
theme_classic(base_size = 20, base_family = "") +
theme(panel.grid.minor = element_line(colour="grey", size=0.5)) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

#add the number of observations
foo <- ggplot_build(p1)$data[[1]]
p2<-p1 + annotate("text", x = foo$x, y = foo$y + 50000, label = C_Em_df[C_Em_df$Type=="Sum",]$n, size = 4.5)

#Plot Percentage values
p3 <- ggplot(C_Em_df[C_Em_df$Type=="Percentage",], aes(x = Driver, y = Value, fill = Period, width = .85)) +
geom_bar(position = "dodge", stat = "identity") +
scale_y_continuous(labels = percent_format(), limits=c(0,1))+
labs(x = "", y = "Carbon Emissions (%)") +
theme(axis.text = element_text(size = 16),
axis.title = element_text(size = 20),
legend.title = element_text(size = 20, face = 'bold'),
legend.text= element_text(size=20),
axis.line = element_line(colour = "black"))+
scale_fill_grey("Period") +
theme_classic(base_size = 20, base_family = "") +
theme(panel.grid.minor = element_line(colour="grey", size=0.5)) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

# Plot two graphs together
install.packages("gridExtra")
library(gridExtra)
gA <- ggplotGrob(p2)
gB <- ggplotGrob(p3)
maxWidth = grid::unit.pmax(gA$widths[2:5], gB$widths[2:5])
gA$widths[2:5] <- as.list(maxWidth)
gB$widths[2:5] <- as.list(maxWidth)

p4 <- arrangeGrob(
gA, gB, nrow = 2, heights = c(0.80, 0.80))

Create ggplots with the same scale in R

We can use a mix of the breaks argument in scale_y_continuous to ensure that we have consistent axis ticks, then use coord_cartesian to ensure that we force both plots to have the same y-axis range.

df1 <- data.frame(val = c(0.2, 0.35, 0.5, 0.65), labels = c('A', 'B', 'C', 'D'))
df2 <- data.frame(val = c(0.4, 0.8, 1.2), labels = c('E', 'F', 'G'))

g_plot <- function(df) {
ggplot(data = df,
aes(x = factor(labels),
y = val,
fill = val)) +
geom_bar(stat = 'identity') +
scale_fill_gradient2(low=LtoM(100), mid='snow3',
high=LtoM(100), space='Lab') +
geom_text(aes(label = val), vjust = -1, fontface = "bold") +
scale_y_continuous(breaks = seq(0, 1.2, 0.2)) +
coord_cartesian(ylim = c(0, 1.2)) +
labs(title = "Title", y = "Value", x = "Methods") +
theme(legend.position = "none")
}

bar1 <- g_plot(df1);
bar2 <- g_plot(df2);
gridExtra::grid.arrange(bar1, bar2, ncol = 2);

Example

Using two scale colour gradients ggplot2

First, note that the reason ggplot doesn't encourage this is because the plots tend to be difficult to interpret.

You can get your two color gradient scales, by resorting to a bit of a cheat. In geom_point certain shapes (21 to 25) can have both a fill and a color. You can exploit that to create one layer with a "fill" scale and another with a "color" scale.

# dummy up data
dat1<-data.frame(log2=rnorm(50), p.value= runif(50))
dat2<-data.frame(log2=rnorm(50), p.value= runif(50))

# geom_point with two scales
p <- ggplot() +
geom_point(data=dat1, aes(x=p.value, y=log2, color=p.value), shape=21, size=3) +
scale_color_gradient(low="red", high="gray50") +
geom_point(data= dat2, aes(x=p.value, y=log2, shape=shp, fill=p.value), shape=21, size=2) +
scale_fill_gradient(low="gray90", high="blue")
p

Sample Image

Custom y-axis scale and secondary y-axis labels in ggplot2 3.1.0

Here is a solution that works with ggplot2 version 3.1.0 using sec_axis(), and which only requires creating a single plot. We still use sec_axis() as before, but rather than scaling the transform by 1/2 for the secondary axis, we inverse scale the breaks on the secondary axis instead.

In this particular case we have it fairly easy, as we simply have to multiply the desired breakpoint positions by 2. The resulting breakpoints are then correctly positioned for both the logarithmic and linear portions of your graph. After that, all we have to do is to relabel the breaks with their desired values. This sidesteps the problem of ggplot2 getting confused by the break placement when it has to scale a mixed transform, as we do the scaling ourselves. Crude, but effective.

Unfortunately, at the present moment there don't appear to be any other alternatives to sec_axis() (other than dup_axis() which will be of little help here). I'd be happy to be corrected on this point, however! Good luck, and I hope this solution proves helpful for you!

Here's the code:

# Vector of desired breakpoints for secondary axis
sec_breaks <- c(0.001, 0.01, 0.1, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5)
# Vector of scaled breakpoints that we will actually add to the plot
scaled_breaks <- 2 * sec_breaks

ggplot(data = dat, aes(x = x, y = y)) +
geom_line(size = 1) +
scale_y_continuous(trans = magnify_trans_log(interval_low = 0.5,
interval_high = 1,
reducer = 0.5,
reducer2 = 8),
breaks = c(0.001, 0.01, 0.1, 0.5, 0.6, 0.7, 0.8, 0.9, 1),
sec.axis = sec_axis(trans = ~.,
breaks = scaled_breaks,
labels = sprintf("%.3f", sec_breaks))) +
theme_bw() +
theme(axis.text.y=element_text(colour = "black", size=15))

And the resulting plot:

Sample Image



Related Topics



Leave a reply



Submit