I have a kind of data such as:
y<-rep(c(1, 2, 3), times=5)
group<-rep(c("a", "b", "c", "d", "e"), each=3)
x<-c(2, 3, 4, 5, 7, 10, 10, 15, 19, 8, 10, 14, 25, 28, 33)
a<-data.frame (x, y, group)
and when I use facet_grid() with scales="free_x" option I obtain 5 graphs with different number of breaks. It is possible that the 5 graphs have the same number of breaks? For example 3.
ggplot(a, aes(x, y))+geom_point()+ facet_grid(~group, scales="free_x")
I know that if I remove the scales="free_x" option I obtain the same scale for the 5 graphs, but the plot it turns so ugly. Can you help me?
You can define your own favorite breaks function. In the example below, I show equally spaced breaks. Note that the x in the function has a range that is already expanded by the expand argument to scale_x_continuous. In this case, I scaled it back (for the multiplicative expand argument).
# loading required packages
require(ggplot2)
require(grid)
# defining the breaks function,
# s is the scaling factor (cf. multiplicative expand)
equal_breaks <- function(n = 3, s = 0.05, ...){
function(x){
# rescaling
d <- s * diff(range(x)) / (1+2*s)
seq(min(x)+d, max(x)-d, length=n)
}
}
# plotting command
p <- ggplot(a, aes(x, y)) +
geom_point() +
facet_grid(~group, scales="free_x") +
# use 3 breaks,
# use same s as first expand argument,
# second expand argument should be 0
scale_x_continuous(breaks=equal_breaks(n=3, s=0.05),
expand = c(0.05, 0)) +
# set the panel margin such that the
# axis text does not overlap
theme(axis.text.x = element_text(angle=45),
panel.margin = unit(1, 'lines'))
Related
How do I change hexbin plots scales?
I currently have this:
Instead of the scale jumping from 1 to 718, I would like it to go from 1 to 2, 3, 5, 10, 20, 40, 80, 160, 320, 640, 1280, 2560, 5120, 10240, 15935.
Here is the code I used to plot it:
hex <- hexbin(trial$pickup_longitude, trial$pickup_latitude, xbins=600)
plot(hex, colramp = colorRampPalette(LinOCS(12)))
Here's a ggplot method, where you can specify whatever breaks you want.
library(ggplot2)
library(RColorBrewer)
##
# made up sample
#
set.seed(42)
X <- rgamma(10000, shape=1000, scale=1)
Y <- rgamma(10000, shape=10, scale=100)
dt <- data.table(X, Y)
##
# define breaks and labels for the legend
#
brks <- c(0, 1, 2, 5, 10, 20, 50, 100, Inf)
n.br <- length(brks)
labs <- c(paste('<', brks[2:(n.br-1)]), paste('>', brks[n.br-1]))
##
#
ggplot(dt, aes(X, Y))+geom_hex(aes(fill=cut(..count.., breaks=brks)), color='grey80')+
scale_fill_manual(name='Count', values = rev(brewer.pal(8, 'Spectral')), labels=labs)
You cannot control the boundaries of the scale as closely as you want, but you can adjust it somewhat. First we need a reproducible example:
set.seed(42)
X <- rnorm(10000, 10, 3)
Y <- rnorm(10000, 10, 3)
XY.hex <- hexbin(X, Y)
To change the scale we need to specify a function to use on the counts and an inverse function to reverse the transformation. Now, three different scalings:
plot(XY.hex) # Linear, default
plot(XY.hex, trans=sqrt, inv=function(x) x^2) # Square root
plot(XY.hex, trans=log, inv=function(x) exp(x)) # Log
The top plot is the original scaling. The bottom left is the square root transform and the bottom right is the log transform. There are probably too many levels to read these plots clearly. Adding the argument colorcut=6 to the plot command would reduce the number of levels to 5.
This question already has answers here:
Adding minor tick marks to the x axis in ggplot2 (with no labels)
(4 answers)
Closed last month.
This question has been raised a number of times on StackOverflow over the years (see here and here), however I'm yet to come across a way that I'm satisfied with for easily adding unlabelled minor ticks to my ggplot axes.
Let's generate some dummy data to play around with:
df <- data.frame(x = rnorm(1000, mean = 25, sd = 5),
y = rnorm(1000, mean = 23, sd = 3))
There are two methods I've come across for adding unlabelled minor ticks.
Method 1 - Manually construct axis label vectors
Concatenate the values that you would like to appear at major ticks with empty spaces defined using "". If you would like to add just one unlabelled minor tick in-between major tick values, you can construct the vector of axis labels like so:
axis_values <- c(0, "", 10, "", 20, "", 30, "", 40, "", 50)
Or if you'd like n unlabelled minor ticks:
# Where n = 2 and for an axis range [0, 50]
axis_values <- c(0, rep("", 2), 15, rep("", 2), 30, rep("", 2), 45, "")
The user can then supply this vector to the 'labels' argument in the ggplot2::scale_x_continuous or ggplot2::scale_y_continuous functions as long as the length of the vector of labels matches the length of the vector supplied to the 'breaks' argument in the same functions.
ggplot(df, aes(x = x, y = y)) +
geom_point() +
scale_x_continuous(breaks = seq(0, 50, 5), labels = axis_values, limits = c(0, 50)) +
scale_y_continuous(breaks = seq(0, 50, 5), labels = axis_values, limits = c(0, 50))
Method 2 - Define your own function for generating axis label vectors
This post describes a function to which the user can supply a vector of values to appear at major ticks, along with the number of unlabelled minor ticks desired:
insert_minor <- function(major_labs, n_minor) {
labs <- c( sapply( major_labs, function(x) c(x, rep("", n_minor) ) ) )
labs[1:(length(labs)-n_minor)]
}
# Generate plot
ggplot(df, aes(x = x, y = y)) +
geom_point() +
scale_x_continuous(breaks = seq(0, 50, 5), labels = insert_minor(major_labs = seq(0, 50, 10),
n_minor = 1), limits = c(0, 50)) +
scale_y_continuous(breaks = seq(0, 50, 5), labels = insert_minor(major_labs = seq(0, 50, 10),
n_minor = 1), limits = c(0, 50))
Method 2 is the best way of generating unlabelled minor ticks I've seen yet. However drawbacks are:
Not dummy-proof - Users need to make sure that the value given to the 'n_minor' argument is compatible with the data supplied to the 'breaks' and 'major_labs' arguments. Call me lazy, but I don't want to think about this when I'm trying to produce plots quickly.
Function management required - When you want to use this function in another script, you have to
retrieve it from the last script you used it in, or alternatively perhaps you can package it up in a library to call in future scripts.
In my eyes, the ideal solution is for the ggplot2 developers to add an argument to scale_x_continuous or scale_y_continuous ggplot2 functions that takes a user-defined value for the number of unlabelled minor ticks the user would like to add to their plot axes, which then takes the vector supplied to the 'breaks' argument and determines 'major_labs' in the background out of the user's sight.
Has anyone else found any other way of computing unlabelled minor ticks in ggplot2?
A quick, simple, and kinda sleek solution would be to define this one-liner labelling function that only shows breaks that occur at your chosen multiples:
label_at <- function(n) function(x) ifelse(x %% n == 0, x, "")
So you could do:
ggplot(df, aes(x = x, y = y)) +
geom_point() +
scale_x_continuous(breaks = seq(0, 50, 5), labels = label_at(10),
limits = c(0, 50)) +
scale_y_continuous(breaks = seq(0, 50, 5), labels = label_at(5),
limits = c(0, 50))
Which you can easily take to extremes:
ggplot(df, aes(x = x, y = y)) +
geom_point() +
scale_x_continuous(breaks = 1:50, labels = label_at(10), limits = c(0, 50)) +
scale_y_continuous(breaks = 1:50, labels = label_at(10), limits = c(0, 50))
I have a simple plot below. I log scaled the x-axis and I want the graph to show 0.1, 1, 10. I can't figure out how to override the default of 0.1, 1.0, 10.0.
Is there a way I could change only two of the x-axis labels?
library(ggplot2)
x <- c(0.1, 1, 10)
y <- c(1, 5, 10)
ggplot()+
geom_point(aes(x,y)) +
scale_x_log10()
You could specify labels and breaks in scale_x_log10
library(ggplot2)
x <- c(0.1, 1, 10)
y <- c(1, 5, 10)
ggplot() + geom_point(aes(x,y)) + scale_x_log10(labels = x, breaks = x)
I would like to make geom_ribbon have gradation color.
For example, I have data.frame as below;
df <-data.frame(Day = c(rnorm(300, 3, 2.5), rnorm(150, 7, 2)), # create random data
Depth = c(rnorm(300, 6, 2.5), rnorm(150, 2, 2)),
group = c(rep('A', 300), rep('B', 150))) # add two groups
With this data.frame, I make ggplot using geom_ribbon as below
gg <-
ggplot(data=df,aes(x=Day))+
geom_ribbon(aes(ymin=Depth,ymax=max(Depth)),alpha = 0.25)+
ylim(max(df$Depth),0)+
facet_wrap(~group,scales = "free_x",ncol=2)+
labs(x="Days(d)",y="Depth (m)")
gg
, which makes a following plot;
Here, I would like to make the ribbon have gradation color by the value of y-axis (i.e. df$Depth, in this case). However, I do not how to do it.
I can do it by geom_point as below;
gg <- gg +
geom_point(aes(y=Depth,color=Depth),alpha = 1, shape = 20, size=5)+
scale_color_gradient2(midpoint = 5,
low = "red", mid="gray37", high = "black",
space ="Lab")
gg
But, I want the color gradation on ribbon by filling the ribbon area, not on each point.
Do you have any suggestion to do it with geom_ribbon?
I do not know this is perfect, but I found a solution for what I want as follows;
First, I prepare data.frame;
df <-data.frame(Day = c(rnorm(300, 7, 2), rnorm(150, 5, 1)), # create random data
Depth = c(rnorm(300, 10, 2.5), rnorm(150, 7, 2)),
group = c(rep('A', 300), rep('B', 150))) # add two groups
Second, prepare the gradation background by following the link; log background gradient ggplot
xlength <- ceiling(max(df$Day))
yseq <- seq(0,max(df$Depth), length=100)
bg <- expand.grid(x=0:xlength, y=yseq) # dataframe for all combinations
Third, plot by using ggplot2;
gg <- ggplot() +
geom_tile(data=bg,
aes(x=x, y=y, fill=y),
alpha = 0.75)+ # plot the gradation
scale_fill_gradient2(low='red', mid="gray37", high = "black",
space ="Lab",midpoint = mean(df$Depth)/2)+ #set the color
geom_ribbon(data=df,
aes(x=Day,ymin=0,ymax=Depth),
fill = "gray92")+ #default ggplot2 background color
ylim(max(df$Depth),0)+
scale_x_continuous()+
facet_wrap(~group,scales = "free_x",ncol=2)+
labs(x="Days(d)",y="Depth (m)")+
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank())
gg
I have a plot of polygons that are colored according to a quantitative variable in the dataset being cut off at certain discrete values (0, 5, 10, 15, 20, 25). I currently have a static ggplot() output that "works" the way I intend. Namely, the legend values are the cut off values (0, 5, 10, 15, 20, 25). The static plot is below -
However, when I simply convert this static plot to an interactive plot, the legend values become hexadecimal values (#54278F, #756BB1, etc.) instead of the cut off values (0, 5, 10, 15, 20, 25). A screenshot of this interactive plot is shown below -
I am trying to determine a way to change the legend labels in the interactive plot to be the cut off values (0, 5, 10, 15, 20, 25). Any suggestions or support would be greatly appreciated!
Below is the code I used to create the static and interactive plot:
library(plotly)
library(ggplot2)
library(RColorBrewer)
set.seed(1)
x = abs(rnorm(30))
y = abs(rnorm(30))
value = runif(30, 1, 30)
myData <- data.frame(x=x, y=y, value=value)
cutList = c(5, 10, 15, 20, 25)
purples <- brewer.pal(length(cutList)+1, "Purples")
myData$valueColor <- cut(myData$value, breaks=c(0, cutList, 30), labels=rev(purples))
# Static plot
sp <- ggplot(myData, aes(x=x, y=y, fill=valueColor)) + geom_polygon(stat="identity") + scale_fill_manual(labels = as.character(c(0, cutList)), values = levels(myData$valueColor), name = "Value")
# Interactive plot
ip <- ggplotly(sp)
Label using the cut points and use scale_fill_manual for the colors.
cutList = c(5, 10, 15, 20, 25)
purples <- brewer.pal(length(cutList)+1, "Purples")
myData$valueLab <- cut(myData$value, breaks=c(0, cutList, 30), labels=as.character(c(0, cutList)))
# Static plot
sp <- ggplot(myData, aes(x=x, y=y, fill=valueLab)) + geom_polygon(stat="identity") + scale_fill_manual(values = rev(purples))
# Interactive plot
ip <- ggplotly(sp)