How to Get a Reversed, Log10 Scale in Ggplot2

How to get a reversed, log10 scale in ggplot2?

The link that @joran gave in his comment gives the right idea (build your own transform), but is outdated with regard to the new scales package that ggplot2 uses now. Looking at log_trans and reverse_trans in the scales package for guidance and inspiration, a reverselog_trans function can be made:

library("scales")
reverselog_trans <- function(base = exp(1)) {
trans <- function(x) -log(x, base)
inv <- function(x) base^(-x)
trans_new(paste0("reverselog-", format(base)), trans, inv,
log_breaks(base = base),
domain = c(1e-100, Inf))
}

This can be used simply as:

p + scale_x_continuous(trans=reverselog_trans(10))

which gives the plot:

Sample Image

Using a slightly different data set to show that the axis is definitely reversed:

DF <- data.frame(x=1:10,  y=1:10)
ggplot(DF, aes(x=x,y=y)) +
geom_point() +
scale_x_continuous(trans=reverselog_trans(10))

Sample Image

How to reverse axis y predetermined from scale_y_log10? ggplot [repeated]

An answer has been provided here.
Applying this to your question I was able to reverse the log axis by applying the transformation function in scale_y_continous:

library("scales")
reverselog_trans <- function(base = exp(1)) {
trans <- function(x) -log(x, base)
inv <- function(x) base^(-x)
trans_new(paste0("reverselog-", format(base)), trans, inv,
log_breaks(base = base),
domain = c(1e-100, Inf))
}

ggplot(dt, mapping = aes(y = dmean, x = area, color = sex, fill=sex))+
geom_violin(alpha=.5,scale = "width",trim = FALSE, position=position_dodge(1))+
ggtitle("Dive mean per area and sex")+
scale_y_continuous(trans = reverselog_trans(10), breaks = c(10, 30, 50, 100, 200, 300, 400, 500))
scale_fill_discrete(name="Social class",
labels=c("Female", "Male"))+
xlab("Habitat")+
ylab("Dive depth (m)")+
theme_bw()+
scale_x_discrete(labels= leg)

Sample Image

How to reverse bars on log scale in geom_col?

Here's a hack where we shift the plotted values to be >1, then shift the labels the same amount:

(Btw I would second the comment that bar charts will be unavoidably misleading on a log scale, since we are taught to interpret length as proportional to value. geom_point might be a simpler choice here, avoiding the need for any adjustments.)

data %>%
ggplot(aes(periodo, valor*1e5, fill = nombre)) +
geom_col(position = position_dodge2(width = 0.3, preserve = "single")) +
scale_y_continuous(name = "valor",
trans = "log10",
limits = 10^c(0, 5),
breaks = 10^c(0:5),
labels = scales::scientific(10^c(-5:0))
)

Sample Image

Expand y axis to negative numbers on a log10 scale axis in ggplot2

You can't make a logged y-scale go negative - logs of a negative number are undefined. Just make it go closer to 0. Here's your graph with

scale_y_log10(limits=c(.1, 1000),breaks=c(1, 10, 100, 1000))

Sample Image

If you want more (will depend on the size of the final plot, size of the text, amount of your vjust), go to 0.05, or 0.01...

I'd also highly recommend using a Date format for your x-axis data, look how much nicer these axis labels are (and how the plot looks cleaner with fewer vertical gridlines).

df1_InSAP_Only$date = as.Date(paste0(df1_InSAP_Only$Year_Month, "_01"), format = "%Y_%m_%d")

# use date column on x-axis
# reduce vjust amounts
# get rid of meaningless group_by() statements
# get rid of unused position dodges
ggplot(df1_InSAP_Only,
aes(x=date,
y=`Duration Average`,
group=Business,
color=Business,
size=`MMR Count`)) +
geom_line(aes(group=Business),stat="identity", size=1, alpha=0.7) +
geom_point(aes(colour=Business, alpha=0.7)) +
facet_wrap(~ Business, ncol=2) +
scale_y_log10( limits=c(.1,1000),breaks=c(1,10,100,1000)) +
scale_alpha_continuous(range = c(0.5,1), guide='none') + #remove the legend for alpha
geom_text(aes(label=`Duration Average`,vjust=-1),
size=3) +
geom_text(aes(label=`MMR Count`,vjust=2),
size=3,
color="brown")

Sample Image

ggplot2: log10-scale and axis limits

ggplot(data = df,aes(x = x, y =y)) + 
geom_point() +
scale_y_log10(limits = c(1,1e8), expand = c(0, 0))

Sample Image

breaks at integer powers of ten on ggplot2 log10 axes

Here is an approach that at the core has the following function.

breaks = function(x) {
brks <- extended_breaks(Q = c(1, 5))(log10(x))
10^(brks[brks %% 1 == 0])
}

It gives extended_breaks() a narrow set of 'nice numbers' and then filters out non-integers.

This gives us the following for you example case:

library(ggplot2)
library(scales)
#> Warning: package 'scales' was built under R version 4.0.3

# dummy data
df <- data.frame(fct = rep(c("A", "B", "C"), each = 3),
x = rep(1:3, 3),
y = 10^seq(from = -4, to = 1, length.out = 9))

ggplot(df, aes(x, y)) +
geom_point() +
facet_wrap(~ fct, scales = "free_y") +
scale_y_continuous(
trans = "log10",
breaks = function(x) {
brks <- extended_breaks(Q = c(1, 5))(log10(x))
10^(brks[brks %% 1 == 0])
},
labels = math_format(format = log10)
)

Sample Image

Created on 2021-01-19 by the reprex package (v0.3.0)

I haven't tested this on many other ranges that might be difficult, but it should generalise better than setting the number of desired breaks to 1. Difficult ranges might be those just in between -but not including- powers of 10. For example 11-99 or 101-999.



Related Topics



Leave a reply



Submit