条形图由线连接/如何连接两个以grid.arrange排列的图形R / ggplot2

Ben

在Facebook研究中,我发现了这些漂亮的条形图,这些条形图通过线相连以指示等级变化: Facebook的解决方案

https://research.fb.com/do-jobs-run-in-families/

我想使用ggplot2创建它们。条形图部分很简单:

library(ggplot2)
library(ggpubr)
state1 <- data.frame(state=c(rep("ALABAMA",3), rep("CALIFORNIA",3)), 
                 value=c(61,94,27,10,30,77), 
                 type=rep(c("state","local","fed"),2),
                 cumSum=c(rep(182,3), rep(117,3)))
state2 <- data.frame(state=c(rep("ALABAMA",3), rep("CALIFORNIA",3)), 
                 value=c(10,30,7,61,94,27), 
                 type=rep(c("state","local","fed"),2),
                 cumSum=c(rep(117,3), rep(182,3)))
fill <- c("#40b8d0", "#b2d183", "#F9756D")

p1 <- ggplot(data = state1) +
  geom_bar(aes(x = reorder(state, value), y = value, fill = type), stat="identity") +
  theme_bw() + 
  scale_fill_manual(values=fill) + 
  labs(x="", y="Total budget in 1M$") +
  theme(legend.position="none", 
        legend.direction="horizontal", 
        legend.title = element_blank(),
        axis.line = element_line(size=1, colour = "black"),
        panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank(),
        panel.border = element_blank(), panel.background = element_blank()) +
  coord_flip() 

p2 <- ggplot(data = state2) +
  geom_bar(aes(x = reorder(state, value), y = value, fill = type), stat="identity") +
  theme_bw() + 
  scale_fill_manual(values=fill) + labs(x="", y="Total budget in 1M$") +
  theme(legend.position="none", 
        legend.direction="horizontal", 
        legend.title = element_blank(),
        axis.line = element_line(size=1, colour = "black"),
        panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank(),
        panel.border = element_blank(), 
        panel.background = element_blank()) +
  scale_x_discrete(position = "top") + 
  scale_y_reverse() +
  coord_flip()

p3 <- ggarrange(p1, p2, common.legend = TRUE, legend = "bottom")

但是我无法提出解决方案。当添加线,例如到左侧

p3 + geom_segment(aes(x = rep(1:2, each=3), xend = rep(1:10, each=3), 
                   y = cumSum[order(cumSum)], yend=cumSum[order(cumSum)]+10), size = 1.2)

问题是这些线将无法越过右侧。看起来像这样:到目前为止我的版本

基本上,我想将左边的“加利福尼亚”栏与右边的“加利福尼亚”栏连接起来。

To do that, I think, I have to get access to the superordinate level of the graph somehow. I've looked into viewports and was able to overlay the two bar charts with a chart made out of geom_segment but then I couldn't figure out the right layout for the lines:

subplot <- ggplot(data = state1) + 
  geom_segment(aes(x = rep(1:2, each=3), xend = rep(1:2, each=3), 
                   y = cumSum[order(cumSum)], yend =cumSum[order(cumSum)]+10), 
               size = 1.2)

vp <- viewport(width = 1, height = 1, x = 1, y = unit(0.7, "lines"), 
               just ="right", "bottom"))
print(p3)
print(subplot, vp = vp)

Help or pointers are greatly appreciated.

camille

This is a really interesting problem. I approximated it using the patchwork library, which lets you add ggplots together and gives you an easy way to control their layout—I much prefer it to doing anything grid.arrange-based, and for some things it works better than cowplot.

I expanded on the dataset just to get some more values in the two data frames.

library(tidyverse)
library(patchwork)

set.seed(1017)

state1 <- data_frame(
  state = rep(state.name[1:5], each = 3),
  value = floor(runif(15, 1, 100)),
  type = rep(c("state", "local", "fed"), times = 5)
)

state2 <- data_frame(
  state = rep(state.name[1:5], each = 3),
  value = floor(runif(15, 1, 100)),
  type = rep(c("state", "local", "fed"), times = 5)
)

Then I made a data frame that assigns ranks to each state based on other values in their original data frame (state1 or state2).

ranks <- bind_rows(
  state1 %>% mutate(position = 1),
  state2 %>% mutate(position = 2)
)  %>%
  group_by(position, state) %>%
  summarise(state_total = sum(value)) %>%
  mutate(rank = dense_rank(state_total)) %>%
  ungroup()

I made a quick theme to keep things very minimal and drop axis marks:

theme_min <- function(...) theme_minimal(...) +
  theme(panel.grid = element_blank(), legend.position = "none", axis.title = element_blank())

The bump chart (the middle one) is based on the ranks data frame, and has no labels. Using factors instead of numeric variables for position and rank gave me a little more control over spacing, and lets the ranks line up with discrete 1 through 5 values in a way that will match the state names in the bar charts.

p_ranks <- ggplot(ranks, aes(x = as.factor(position), y = as.factor(rank), group = state)) +
  geom_path() +
  scale_x_discrete(breaks = NULL, expand = expand_scale(add = 0.1)) +
  scale_y_discrete(breaks = NULL) +
  theme_min()
p_ranks

For the left bar chart, I sort the states by value and turn the values negative to point to the left, then give it the same minimal theme:

p_left <- state1 %>%
  mutate(state = as.factor(state) %>% fct_reorder(value, sum)) %>%
  arrange(state) %>%
  mutate(value = value * -1) %>%
  ggplot(aes(x = state, y = value, fill = type)) +
    geom_col(position = "stack") +
    coord_flip() +
    scale_y_continuous(breaks = NULL) +
    theme_min() +
    scale_fill_brewer()
p_left

The right bar chart is pretty much the same, except the values stay positive and I moved the x-axis to the top (becomes right when I flip the coordinates):

p_right <- state2 %>%
  mutate(state = as.factor(state) %>% fct_reorder(value, sum)) %>%
  arrange(state) %>%
  ggplot(aes(x = state, y = value, fill = type)) +
    geom_col(position = "stack") +
    coord_flip() +
    scale_x_discrete(position = "top") +
    scale_y_continuous(breaks = NULL) +
    theme_min() +
    scale_fill_brewer()

Then because I've loaded patchwork, I can add the plots together and specify the layout.

p_left + p_ranks + p_right +
  plot_layout(nrow = 1)

您可能需要更多地调整间距和边距,例如expand_scale通过凹凸图调用。我还没有尝试过沿y轴使用轴标记(即翻转后的底部),但是我有种感觉,如果不将虚拟轴添加到等级中,事情可能会被甩掉。仍然有很多问题要摆弄,但这是您提出的一个很酷的可视化项目!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

ggplot2条形图,带有两个分类变量

ggplot2中的单个条形图,R

向R中的ggplot2中的堆叠条形图添加水平线,并在图例中显示

R:ggplot2轴显示两个范围

使用ggplot2在一张图中绘制两个单独的条形图

如何使用geom_bar在ggplot2中制作连接的条形图?

如何在ggplot2中的“ grid.arrange”中的特定位置留下没有图形的间隙

如何使用R的ggplot2包更改条形图的颜色?

R ggplot2条形图,条形图上有圆角

ggplot2中条形图的计数和百分比如何?[R

R ggplot2条形图

R:连接图形上的点(ggplot2)

用线连接ggplot2图形中的点

如何将条形图和参数估计图结合为一个图形。ggplot2

对具有两个级别ggplot2的堆叠条形图进行重新排序

ggplot2:如何按填充变量的比例重新排列堆积的条形图

R ggplot2条形图更改特定条形的颜色

带有ggplot2的R中的条形图

使用ggplot2在R上分组的条形图

向ggplot2 R中的堆叠条形图添加误差线-已解决

如何使用ggplot2在条形图中排列y轴

在 R 和 ggplot2 的条形图中排列条形时出现“na”问题

如何使用 ggplot2 在 R 中重新排序此条形图?

如何在R中从最高到最低对条形图进行排序?(ggplot2)

如何使用 ggplot2 在 R 中创建分组和堆积条形图

通过使用 ggplot2 连接两个点在 R 中绘制多个图

如何使用ggplot2在r中添加条形图频率的实际大小?

如何返回预期的图形(ggplot2,r 中的椭圆)?

如何使用 ggplot2 在 R 中绘制包含不同组的条形图?