Is it possible to jitter two ggplot geoms in the same way?
This is a weakness in the current ggplot2 syntax - there's no way to work around it except to add the jitter yourself.
Or you could do something like this:
ggplot(baseball, aes(round(year,-1) + as.numeric(factor(lg)), sb, color = factor(lg))) +
stat_summary(fun.data="mean_cl_normal") +
stat_summary(fun.y=mean,geom="line") +
coord_cartesian(ylim=c(0,40))
Apply jitter uniformly across geoms in ggplot2
Using position_jitter
function, you can add a seed
value to get reproducible jitter effect:
library(ggplot2)
ggplot(pdat, aes(x = x, y = y, ymin = ymin, ymax = ymax, color = colour))+
geom_point(position = position_jitter(seed = 123, width =0.2))+
geom_linerange(position = position_jitter(seed = 123, width = 0.2))
Does it answer your question ?
How to jitter both geom_line and geom_point by the same magnitude?
Another option for horizontal only would be to specify position_dodge
and pass this to the position
argument for each geom.
pd <- position_dodge(0.4)
ggplot(data = df, aes(x = dimension, y = value,
shape = Time, linetype = Time, group = Time)) +
geom_line(position = pd) +
geom_point(position = pd) +
xlab("Dimension") + ylab("Value")
Highlighting some points with constant jitter across plots (ggplot2)
As compared to your solution of layering two jitters, the fill
approach was in the right direction. However, fill
works only for shapes 21-25, so you were not able to see the desired result.
Graph with all points:
myseed=101
set.seed(myseed)
p <- ggplot(dr, aes(x=X,y=Y,colour=Y)) +
theme_bw() +
geom_jitter(alpha=0.7,width=0.5, size = 3) +
scale_colour_gradient("Y", low="#5edcff", high="#035280") +
stat_summary(fun.y = "mean", fun.ymin = "mean", fun.ymax= "mean", size=0.3,width=0.33, geom = "crossbar")
plot(p)
Graph with highlighted points:
Note that I supplied aesthetics
to stat_summary
again, otherwise it would generate another summary for the fill
layer.
myseed=101
set.seed(myseed)
p <- ggplot(dr, aes(x=X,y=Y,colour=Y, fill = factor(highlight))) +
theme_bw() +
geom_jitter(width=0.5, shape = 21, size = 3) +
scale_colour_gradient("Y", low="#5edcff", high="#035280") +
scale_fill_manual(values=c("red"), guide = FALSE) +
stat_summary(aes(x=X,y=Y,colour=Y), inherit.aes = FALSE,
fun.y = "mean", fun.ymin = "mean", fun.ymax= "mean", size=0.3,width=0.33, geom = "crossbar")
plot(p)
I still think a cleaner solution would be to manually code the colors, but I did not attempt it. Maybe someone will supply that solution.
Subdividing jitter points in ggplot
Found a solution using:
geom_point(position=position_jitterdodge())
This seems to jitter and dodge to separate the points.
Jitter geom_line and geom_point
You can pass the argument seed
into position_jitter
in order to make the same jitter effect between geom_point
and geom_line
:
ggplot(data = test, aes(
x = time_point, y = Q10, color = storage_temp
)) +
geom_point(
data = test,
aes(time_point, Q10, group = storage_temp),
alpha = 0.25,
color = 'black',
position = position_jitter(width = 0.25, seed = 123)
) +
geom_line(
data = test,
aes(group = individual_code, linetype = storage_temp),
color = 'black',
alpha = 0.25,
position = position_jitter(width = 0.25, seed = 123)
)
Does it answer your question ?
selective jitter of geom_points
We can use duplicated
or any similar function to detect the overlap, then we can use R indexing with jitter
to apply jitter selectively.
I wrote it as a function:
selective_jitter <- function(x, # x = x co-ordinate
y, # y = y co-ordinate
g # g = group
){
x <- as.numeric(x)
y <- as.numeric(y)
a <- cbind(x, y)
a[duplicated(a)] <- jitter(a[duplicated(a)], amount = .15) # amount could be made a parameter
final <- cbind(a, g)
return(final)
}
data <- as.data.frame(selective_jitter(data$x, data$y, data$type))
ggplot() + geom_point(data = data, aes(x=x,y=y, color = g, fill = type), size = 2, shape = 25)
There are a lot of ways to write this differently or to tweak it. For instance, I think a very nice tweak would be to add an optional argument for the amount
option of jitter()
.
Another potential improvement would be to use a caliper to look for (near-) duplicates as well as the exact duplicates (whereas duplicated
will just find exact dupes).
Final note - sometimes when I do this I like to use semi-transparent colors rather than jitter
. This variation works well only if the number of series (type
) is small, so that you can do things like have 1 series in yellow, 1 in blue, and then their overlap would be green (there are existing solutions on Stack Overflow) that demonstrate that if you're interested.
How is jitter determined in ggplot?
If we look at the source we first find this:
PositionJitter <- proto(Position, {
objname <- "jitter"
adjust <- function(., data) {
if (empty(data)) return(data.frame())
check_required_aesthetics(c("x", "y"), names(data), "position_jitter")
if (is.null(.$width)) .$width <- resolution(data$x, zero = FALSE) * 0.4
if (is.null(.$height)) .$height <- resolution(data$y, zero = FALSE) * 0.4
trans_x <- NULL
trans_y <- NULL
if(.$width > 0) {
trans_x <- function(x) jitter(x, amount = .$width)
}
if(.$height > 0) {
trans_y <- function(x) jitter(x, amount = .$height)
}
transform_position(data, trans_x, trans_y)
}
})
And wouldn't you know it, resolution
is an exported function (or you could just search the sources for it landing you here):
function (x, zero = TRUE)
{
if (is.integer(x) || zero_range(range(x, na.rm = TRUE)))
return(1)
x <- unique(as.numeric(x))
if (zero) {
x <- unique(c(0, x))
}
min(diff(sort(x)))
}
So...there you go!
"resolution" in this context then roughly means "the smallest distance between any two elements in a vector".
This value (40% of the resolution) is then passed on as the factor
argument to jitter
, which has it's own little song and dance:
The result, say r, is r <- x + runif(n, -a, a) where n <- length(x)
and a is the amount argument (if specified).Let z <- max(x) - min(x) (assuming the usual case). The amount a to be
added is either provided as positive argument amount or otherwise
computed from z, as follows:If amount == 0, we set a <- factor * z/50 (same as S).
If amount is NULL (default), we set a <- factor * d/5 where d is the
smallest difference between adjacent unique (apart from fuzz) x
values.
Related Topics
How to Create a List in R from Two Vectors (One Would Be the Keys, the Other the Values)
Arrange_() Multiple Columns with Descending Order
Clustered Standard Errors in R Using Plm (With Fixed Effects)
Change Color Actionbutton Shiny R
Efficient Apply or Mapply for Multiple Matrix Arguments by Row
How Do Add a Column in a Data Frame in R
Add Missing Value in Column with Value from Row Above
Remove Duplicate Values Based on 2 Columns
Observeevent Shiny Function Used in a Module Does Not Work
How to Show the Progress of Code in R
Adding R^2 on Graph with Facets
How to Increase the Space Between Grouped Bars in Ggplot2
How to Edit and Save Changes Made on Shiny Datatable Using Dt Package
How to Extract Data from a Rasterbrick