Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plot_layout(guides = "collect") & theme(legend.position = 'bottom') printed a vertical legends #137

Closed
seheeopark opened this issue Dec 4, 2019 · 6 comments

Comments

@seheeopark
Copy link

I have two ggraphs to patch.

library(tidygraph)
library(ggraph) 

g1 <- gsi_wave1 %N>% 
  mutate(degree_sum = centrality_degree(mode = "all")) %>% 
  ggraph(layout = "kk") +
  geom_edge_link(aes(alpha = 0.5),
                 # Add arrow points 
                 arrow = arrow(length = unit(1, "mm")),
                 start_cap = circle(0.5, "mm"),
                 end_cap = circle(0.5, "mm")) +
  geom_node_point(aes(color = degree_sum,
                      alpha = 0.8)) + 
  scale_color_viridis(discrete = FALSE, option = "D") +
  theme_void() +
  ggtitle("GSI Network in wave 1 (2008-2010)")

g2 <- gsi_wave3 %N>% 
  mutate(degree_sum = centrality_degree(mode = "all")) %>% 
  ggraph(layout = "kk") +
  geom_edge_link(aes(alpha = 0.5),
                 # Add arrow points 
                 arrow = arrow(length = unit(1, "mm")),
                 start_cap = circle(0.5, "mm"),
                 end_cap = circle(0.5, "mm")) +
  geom_node_point(aes(color = degree_sum,
                      alpha = 0.8)) + 
  scale_color_viridis(discrete = FALSE, option = "D") +
  theme_void() +
  ggtitle("GSI Network in wave 3 (2015-2017)")

library(patchwork) 
g1 + g2 + plot_layout(guides = 'collect') & theme(legend.position = 'bottom')

The patched plot shows a collected legend in a vertical format.
plot_zoom

How can I get a collected legend in a horizontal format as in the individual graph?

@seheeopark seheeopark changed the title plot_layout(guides = "collect") & theme(legend.position = 'bottom') printed a vertical list plot_layout(guides = "collect") & theme(legend.position = 'bottom') printed a vertical legends Dec 4, 2019
@llrs
Copy link

llrs commented Dec 4, 2019

I think that the color scale should be between the same values in order to be collected, this also applies to the alpha (and probably should use the same line type in both plots).

BTW you didn't show the code used to compose these plots and I couldn't run the code you have because I don't know how to generate gsi_wave1 nor gsi_wave3.

@seheeopark
Copy link
Author

Hello Lluís

Two graphs shared the same alpha for nodes and edges, and they are indeed collected.
I understand that the degree_sum legends are not collected for having different scales.

What I am curious about is why the collected 'bottom' legend takes a vertical format.
If they are not collected, the labs of legends are in a horizontal format as this.

library(patchwork) 
g1 + g2 

plot_zoom2

Let me share the network data here (I had to delete other detailed node information, but the nodes and edges are the same): gsi_network.zip
Please note the changed data names:

  • gsi_wave1_pb (gsi_wave1)
  • gsi_wave3_pb (gsi_wave3)

Thank you for your time and help.

@llrs
Copy link

llrs commented Dec 5, 2019

Interestingly alpha and edge link gott collected but not the color.

However, now that I look closer to the code if you have a fixed aesthetic you should use it outside the aes call (this will remove the guides for them):

g1 <- gsi_wave1 %N>% 
  mutate(degree_sum = centrality_degree(mode = "all")) %>% 
  ggraph(layout = "kk") +
  geom_edge_link(alpha = 0.5,
                 # Add arrow points 
                 arrow = arrow(length = unit(1, "mm")),
                 start_cap = circle(0.5, "mm"),
                 end_cap = circle(0.5, "mm")) +
  geom_node_point(aes(color = degree_sum),
                      alpha = 0.8) + 
  scale_color_viridis(discrete = FALSE, option = "D") +
  theme_void() +
  ggtitle("GSI Network in wave 1 (2008-2010)")

g2 <- gsi_wave3 %N>% 
  mutate(degree_sum = centrality_degree(mode = "all")) %>% 
  ggraph(layout = "kk") +
  geom_edge_link(alpha = 0.5,
                 # Add arrow points 
                 arrow = arrow(length = unit(1, "mm")),
                 start_cap = circle(0.5, "mm"),
                 end_cap = circle(0.5, "mm")) +
  geom_node_point(aes(color = degree_sum),
                      alpha = 0.8) + 
  scale_color_viridis(discrete = FALSE, option = "D") +
  theme_void() +
  ggtitle("GSI Network in wave 3 (2015-2017)")

Surprisingly I got another error when I change the order:

g1 + g2 & theme(legend.position = "bottom")  + plot_layout(guides = 'collect')
Error: Don't know how to add RHS to a theme object

Maybe the difference is that these plots are of class ggraph while ggplot2 plots are of class gg. So it might need a different method for this class.

@jhrcook
Copy link

jhrcook commented Dec 22, 2019

Hello Lluís,

The new error you are getting is from adding the plot_layout() function to the theme() function. Changing the ordering or adding parentheses will likely get the new error resolved.

- Josh

@dleopold
Copy link

dleopold commented Apr 5, 2020

Is there a solution to the initial question? Specifically, how to achieve two horizontal legends "collected" at the bottom, but next to each other instead of aligned vertically?.

@audrey-onfroy
Copy link

This issue is closed since 2020 but not resolved yet.
Maybe legend.direction in theme() answers the initial question :

Quick answer : legend.direction

g1 + g2 + plot_layout(guides = 'collect') &
  theme(legend.position = 'bottom',
        legend.direction = 'horizontal')

Detailed answer (and collect color legend)

Moreover, to collect the color, setting the range the same allows to have only one legend for degree_sum. You should specify the limits in scale_color_viridis, for example :
scale_color_viridis(discrete = FALSE, option = "D", limits = c(0,40)).

I don't know how to extract in a simple way a range from a tbl_graph object but below is a solution. I used lapply to avoid writing two times the function. Then, tidygraph::activate(nodes) on each object to get the Node Data. Then, convert as data frame and extract only the column of interest and keep its range. lapply outputs a list containing the range for each object. Actually, this is [0, 32] and [0, 34]. Applying again range on it get the min of all lower bounds and max of all upper bounds : [0, 34].

gsi_wave1_pb <- gsi_wave1_pb %N>% 
  mutate(degree_sum = centrality_degree(mode = "all"))
gsi_wave3_pb <- gsi_wave3_pb %N>% 
  mutate(degree_sum = centrality_degree(mode = "all"))

degree_sum_range <- lapply(list(gsi_wave1_pb, gsi_wave3_pb),
                          FUN = function(gsi) {
                            gsi %>%
                              tidygraph::activate(nodes) %>%
                              data.frame() %>%
                              dplyr::pull(degree_sum) %>%
                              range()}) %>% range()

I don't change anything in the construction of your plots, but the limits parameter is set to degree_sum_range in scale_color_viridis function. Then, both plots will shared the same legend for color.

g1 <- ggraph(gsi_wave1_pb, layout = "kk") +
  geom_edge_link(aes(alpha = 0.5),
                 # Add arrow points 
                 arrow = arrow(length = unit(1, "mm")),
                 start_cap = circle(0.5, "mm"),
                 end_cap = circle(0.5, "mm")) +
  geom_node_point(aes(color = degree_sum,
                      alpha = 0.8)) + 
  scale_color_viridis(discrete = FALSE, option = "D", limits = degree_sum_range) +
  theme_void() +
  ggtitle("GSI Network in wave 1 (2008-2010)")

g2 <- ggraph(gsi_wave3_pb, layout = "kk") +
  geom_edge_link(aes(alpha = 0.5),
                 # Add arrow points 
                 arrow = arrow(length = unit(1, "mm")),
                 start_cap = circle(0.5, "mm"),
                 end_cap = circle(0.5, "mm")) +
  geom_node_point(aes(color = degree_sum,
                      alpha = 0.8)) + 
  scale_color_viridis(discrete = FALSE, option = "D", limits = degree_sum_range) +
  theme_void() +
  ggtitle("GSI Network in wave 3 (2015-2017)")

For the patchwork, do not forget the legend.direction in theme().

g1 + g2 + plot_layout(guides = 'collect') &
  theme(legend.position = 'bottom',
        legend.direction = 'horizontal')

horizontal

If you set legend.direction to vertical, the legend is displayed in three columns :

g1 + g2 + plot_layout(guides = 'collect') &
  theme(legend.position = 'bottom',
        legend.direction = 'vertical')

vertical

Play also with legend.box

Note that in both figure, legend.box is by default horizontal. Set it vertical to have :

g1 + g2 + plot_layout(guides = 'collect') &
  theme(legend.position = 'bottom',
        legend.direction = 'horizontal',
        legend.box = 'vertical')

horizontal_vertical

g1 + g2 + plot_layout(guides = 'collect') &
  theme(legend.position = 'bottom',
        legend.direction = 'vertical',
        legend.box = 'vertical')

vertical_vertical

Hope it helps !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants