Open pedrocr83 opened 5 years ago
UPDATE: I'm using IF statements to decide which dumbbell graph is drawn first but this seems a subpar solution...
Well met, @pedrocr83!
This is a super interesting request (i.e. making this a more generic function). Lemme ponder a bit what said API would look like.
In the interim, here's an example for how to build this with with three points (it works for n
points, really) "manually"
library(hrbrthemes)
library(tidyverse)
tibble(
val1 = c(3, 2, 4),
val2 = c(1, 4, 5),
val3 = c(5, 8, 6),
cat = factor(month.name[1:3], levels = rev(month.name[1:3]))
) -> xdf
ggplot() +
# this draws leading eye-tracker dotted line from the category name
# to the first point (helps readers follow the values to the categories)
geom_segment(
data = gather(xdf, measure, val, -cat) %>%
group_by(cat) %>%
top_n(-1) %>%
slice(1) %>%
ungroup(),
aes(x = 0, xend = val, y = cat, yend = cat),
linetype = "dotted", size = 0.5, color = "gray80"
) +
# this draws the underlying full segment intelligently choosing
# the correct min/max points
geom_segment(
data = gather(xdf, measure, val, -cat) %>%
group_by(cat) %>%
summarise(start = range(val)[1], end = range(val)[2]) %>%
ungroup(),
aes(x = start, xend = end, y = cat, yend = cat),
color = "gray80", size = 2
) +
# this draws the
geom_point(
data = gather(xdf, measure, value, -cat),
aes(value, cat, color = measure),
size = 4
) +
# i just extended the scale a bit + put axis on top; choose aesthetics that work
# for you
scale_x_comma(position = "top", limits = c(0, 10)) +
scale_color_ipsum(name = "A real legend title") +
labs(
x = "Description of the value", y = NULL,
title = "A good plot title"
) +
theme_ipsum_rc(grid = "X") +
theme(legend.position = "top")
Do not hesitate to ask any and all q's abt ^^. Very glad to lend some assistance.
@hrbrmstr awe...some! Thanks for the effort!
Well met, @pedrocr83!
This is a super interesting request (i.e. making this a more generic function). Lemme ponder a bit what said API would look like.
In the interim, here's an example for how to build this with with three points (it works for
n
points, really) "manually"library(hrbrthemes) library(tidyverse) tibble( val1 = c(3, 2, 4), val2 = c(1, 4, 5), val3 = c(5, 8, 6), cat = factor(month.name[1:3], levels = rev(month.name[1:3])) ) -> xdf ggplot() + # this draws leading eye-tracker dotted line from the category name # to the first point (helps readers follow the values to the categories) geom_segment( data = gather(xdf, measure, val, -cat) %>% group_by(cat) %>% top_n(-1) %>% slice(1) %>% ungroup(), aes(x = 0, xend = val, y = cat, yend = cat), linetype = "dotted", size = 0.5, color = "gray80" ) + # this draws the underlying full segment intelligently choosing # the correct min/max points geom_segment( data = gather(xdf, measure, val, -cat) %>% group_by(cat) %>% summarise(start = range(val)[1], end = range(val)[2]) %>% ungroup(), aes(x = start, xend = end, y = cat, yend = cat), color = "gray80", size = 2 ) + # this draws the geom_point( data = gather(xdf, measure, value, -cat), aes(value, cat, color = measure), size = 4 ) + # i just extended the scale a bit + put axis on top; choose aesthetics that work # for you scale_x_comma(position = "top", limits = c(0, 10)) + scale_color_ipsum(name = "A real legend title") + labs( x = "Description of the value", y = NULL, title = "A good plot title" ) + theme_ipsum_rc(grid = "X") + theme(legend.position = "top")
Do not hesitate to ask any and all q's abt ^^. Very glad to lend some assistance.
Hello @hrbrmstr, thanks for your code! I am trying to use the same idea where I have 3 values on 1 dumbbell. However, when I tried to run your exact code, I run into error. Below I copy the error message generated by R, and would greatly appreciate your help in pointing out where I could go and fix:
Selecting by val Error: Aesthetics must be valid data columns. Problematic aesthetic(s): y = cat, yend = cat. Did you mistype the name of a data column or forget to add after_stat()? Run
rlang::last_error()
to see where the error occurred.
After running rlang::last_error() :
<error/rlang_error> Aesthetics must be valid data columns. Problematic aesthetic(s): y = cat, yend = cat. Did you mistype the name of a data column or forget to add after_stat()? Backtrace:
- (function (x, ...) ...
- ggplot2:::print.ggplot(x)
- ggplot2:::ggplot_build.ggplot(x)
- ggplot2:::by_layer(function(l, d) l$compute_aesthetics(d, plot))
- ggplot2:::f(l = layers[[i]], d = data[[i]])
- l$compute_aesthetics(d, plot)
- ggplot2:::f(..., self = self) Run
rlang::last_trace()
to see the full context.
My R version (if it is relevant)
version _
platform x86_64-w64-mingw32
arch x86_64
os mingw32
system x86_64, mingw32
status
major 4
minor 0.0
year 2020
month 04
day 24
svn rev 78286
language R
version.string R version 4.0.0 (2020-04-24) nickname Arbor Day
Much appreciated for your help in advance!
Elly
@ellyyuyang without the tibble its kinda of hard to debug but i'll give my example after that awesome piece of code @hrbrmstr gave me:
d <- tibble(normal = value1 , notnormal = value2 , sample = value3 , metric = factor(stringvalue))
getComparisonPlot<-function(d) { plot <- ggplot() + geom_segment(data = gather(d, measure, val, -metric) %>% group_by(metric) %>% summarise(start = 0, end = range(val)[2]) %>% ungroup(), aes(x = start, xend = end, y = 0, yend = 0), color = '#DCDDDA', size = 10, lineend = "round") + geom_segment(data = gather(d, measure, val, -metric) %>% group_by(metric) %>% summarise(start = range(val)[1], end = 0) %>% ungroup(), aes(x = start, xend = end, y = 0, yend = 0), color = '#7DB500', size = 10, lineend = "round") return(plot) }
@ellyyuyang without the tibble its kinda of hard to debug but i'll give my example after that awesome piece of code @hrbrmstr gave me:
d <- tibble(normal = value1 , notnormal = value2 , sample = value3 , metric = factor(stringvalue))
getComparisonPlot<-function(d) { plot <- ggplot() + geom_segment(data = gather(d, measure, val, -metric) %>% group_by(metric) %>% summarise(start = 0, end = range(val)[2]) %>% ungroup(), aes(x = start, xend = end, y = 0, yend = 0), color = '#DCDDDA', size = 10, lineend = "round") + geom_segment(data = gather(d, measure, val, -metric) %>% group_by(metric) %>% summarise(start = range(val)[1], end = 0) %>% ungroup(), aes(x = start, xend = end, y = 0, yend = 0), color = '#7DB500', size = 10, lineend = "round") return(plot) }
Hello @pedrocr83 , appreciate your help! It may be due to something iffy happened to my R studio. My issue has been resolved after restarting R studio. Cheers! @hrbrmstr thanks for your code again!
@ellyyuyang without the tibble its kinda of hard to debug but i'll give my example after that awesome piece of code @hrbrmstr gave me:
d <- tibble(normal = value1 , notnormal = value2 , sample = value3 , metric = factor(stringvalue))
getComparisonPlot<-function(d) { plot <- ggplot() + geom_segment(data = gather(d, measure, val, -metric) %>% group_by(metric) %>% summarise(start = 0, end = range(val)[2]) %>% ungroup(), aes(x = start, xend = end, y = 0, yend = 0), color = '#DCDDDA', size = 10, lineend = "round") + geom_segment(data = gather(d, measure, val, -metric) %>% group_by(metric) %>% summarise(start = range(val)[1], end = 0) %>% ungroup(), aes(x = start, xend = end, y = 0, yend = 0), color = '#7DB500', size = 10, lineend = "round") return(plot) }
@pedrocr83 I was trying to play around with the code and explore the possibly of reordering the dumbbells according to one of the variables but failed, would like to see if you would have any insights to it! Much appreciated!
So I tried to reorder the order of months (in @hrbrmstr 's original code) by the val3. so I added the following code before ggplot
xdf %>% mutate(cat = fct_reorder(cat, desc(val3))) %>%
But this does not perform the reordering of the dumbbells. Do you have any thoughts on this?
Best, Elly
@ellyyuyang without the tibble its kinda of hard to debug but i'll give my example after that awesome piece of code @hrbrmstr gave me: d <- tibble(normal = value1 , notnormal = value2 , sample = value3 , metric = factor(stringvalue)) getComparisonPlot<-function(d) { plot <- ggplot() + geom_segment(data = gather(d, measure, val, -metric) %>% group_by(metric) %>% summarise(start = 0, end = range(val)[2]) %>% ungroup(), aes(x = start, xend = end, y = 0, yend = 0), color = '#DCDDDA', size = 10, lineend = "round") + geom_segment(data = gather(d, measure, val, -metric) %>% group_by(metric) %>% summarise(start = range(val)[1], end = 0) %>% ungroup(), aes(x = start, xend = end, y = 0, yend = 0), color = '#7DB500', size = 10, lineend = "round") return(plot) }
@pedrocr83 I was trying to play around with the code and explore the possibly of reordering the dumbbells according to one of the variables but failed, would like to see if you would have any insights to it! Much appreciated!
So I tried to reorder the order of months (in @hrbrmstr 's original code) by the val3. so I added the following code before ggplot
xdf %>% mutate(cat = fct_reorder(cat, desc(val3))) %>%
But this does not perform the reordering of the dumbbells. Do you have any thoughts on this?
Best, Elly
Sorry @ellyyuyang are you still having this issue? somehow i missed the notification
I'm using geom_dumbbell (really cool btw), to plot 3 values on the x-axis to compare the distances between them. Because it only takes x and x_end args i'm using geom_dumbbell twice, efectively solving my problem. However, since my data changes everytime i run the plot sometimes the line connecting x and x_end of the last plot being created goes over one of the points. Can you see a way around this or another way of plotting 3 values using geom_dumbbell. (example attached)