按组手动填充多个比例尺的geom_tile [英] Manual fill geom_tile with multiple scales by group

查看:61
本文介绍了按组手动填充多个比例尺的geom_tile的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下当前输出:

我的目标是这样的着色,但只能填充到最大级别(例如,填充停止在当前级别):

创建此数据的数据是:

  df<-tribble(〜Question_Code,〜RespondentLevel,参与-包容",5外部参与-政策",2外部参与-技术",5,社区数据",5内部参与",5,技术的内部使用",4熟悉/结盟",5环境影响",5,创新",2使用开源技术",2,硬件和软件的规定",第5条,内部技术能力",5,基础设施采购",5算法误差与偏差",2,控制:隐私",5,治理结构中的问责制",第3页,公开采购",5用于决策",1,问责制",1,外部控制",4内部控制",2,开放数据",2)级别<-c(开放数据",内部控制",外部控制",问责制",决策中使用",公开采购",治理结构中的责任制",控制权:隐私权",算法误差和偏差",基础设施采购",内部技术能力",硬件和软件的监管",开源技术的使用",创新",环境影响",熟悉/协调",内部使用技术",内部参与",社区数据",外部参与-技术",外部参与-政策",参与-包容")df<-df%>%mutate(Domain = c(as.character((rep("Domain 1",5))),as.character(rep("Domain 2",4)),as.character(rep("Domain 3",6)),as.character(rep("Domain 4",7)))) 

对于ggplot:

  df%>%ggplot(aes(x = RespondentLevel,y = fct_rev(Question_Code)))+geom_tile()+theme_minimal(16) 

要填充的颜色,我正在使用:

 ,每种颜色对应一个域,每个阴影对应一个级别:绿色<-c(#edf8e9",#bae4b3",#74c476",#31a354",#006d2c")红色<-c(#fee5d9",#fcae91",#fb6a4a",#de2d26",#a50f15")黄色<-c(#ffffeb",#ffff9d",#ffff89",#ffff4e",#ffff14")布鲁斯<-c(#eff3ff",#bdd7e7",#6baed6",#3182bd",#08519c") 

geom_bar也可以解决问题,但不能按渐变细分.尝试使用

对不起,很抱歉,如果可以的话,可以进行调整

解决方案

以下是一些技巧.首先,为了获得每个问题的完整级别,以便您在数据上没有差距,我使用了 tidyr :: complete .那就是我要使用的数据框架.

 库(ggplot2)图书馆(dplyr)图书馆(tidyr)图书馆(purrr)图书馆(拼凑而成)df_full<-df%>%完成(嵌套(域,Question_Code),RespondentLevel)%>%mutate(RespondentLevel = as.character(RespondentLevel)) 

更简单的选项是通过更改alpha并根据域设置色相(红色,绿色等)来近似渐变.这会失去您选择的其他颜色,并且仅使用每个调色板的最后一个最暗的颜色.

为此,我列出了所有调色板.在设置填充时, map_chr(palettes,5)提取每个列表的第5个元素,这是每个列表中最暗的颜色.您可能需要调整或删除其中一个或两个图例.

 调色板<-列表(绿色,红色,黄色,蓝色)ggplot(df_full,aes(x = RespondentLevel,y = Question_Code,fill = Domain,alpha = RespondentLevel))+geom_tile()+theme_minimal()+facet_grid(rows = vars(Domain),scales ="free",space ="free")+scale_fill_manual(值= map_chr(调色板,5))#>警告:不建议对离散变量使用alpha. 

更困难的方法是按域划分数据并绘制图表列表,然后将其与 patchwork 包放在一起.好处是您可以保留完整的调色板,但不利的是,控制从 facet_grid 获得的尺寸调整之类的东西比较困难,因为它会根据清单中列出的更多问题进行调整一些域比其他域.如果您认为这种方法值得,可以在 plot_layout 中手动调整它们的大小.您还需要调整一些主题元素,以模仿 facet_grid 的功能.

  plot_list<-df_full%>%split(.$ Domain)%>%map2(palettes,function(domain_df,pal){ggplot(domain_df,aes(x = RespondentLevel,y = Question_Code,fill = RespondentLevel))+geom_tile()+theme_minimal()+scale_fill_manual(values = pal)+主题(legend.position ="none")+实验室(x = NULL,y = NULL)})reduce(plot_list,`+`)+plot_layout(ncol = 1) 

请注意,通常情况下, patchwork 会将诸如 plot1 + plot2 之类的图放在一起,以模仿 ggplot 分层.由于我已在列表中列出了绘图,因此我使用 purrr :: reduce 进行了此操作.

I have the following current output:

And I am aiming for a colouring like this, but only filled until the maximum level (e.g the fill stops at the level present):

The data to create this, is:

df <- tribble(~Question_Code,   ~RespondentLevel,
"Engagement - Inclusion",   5,
"External engagement - policies",   2,
"External engagement - technology", 5,
"Community data ",  5,
"Internal engagement",  5,
"Internal use of technology",   4,
"Familiarity/Alignment",    5,
"Environmental impacts",    5,
"Innovation",   2,
"Use of open-source technology",    2,
"Regulation of hardware & software",    5,
"In-house technical capacity",  5,
"Infrastructure procurement",   5,
"Algorithmic Error & Bias", 2,
"Control: Privacy", 5,
"Accountability in Governance Structures",  3,
"Open procurement", 5,
"Use in decision-making",   1,
"Accountability",   1,
"External Control", 4,
"Internal Control", 2,
"Open Data",    2)
levels <-  c("Open Data","Internal Control","External Control","Accountability",
             "Use in decision-making","Open procurement","Accountability in Governance Structures","Control: Privacy",
             "Algorithmic Error & Bias","Infrastructure procurement","In-house technical capacity",
             "Regulation of hardware & software","Use of open-source technology","Innovation",
             "Environmental impacts","Familiarity/Alignment",
             "Internal use of technology","Internal engagement","Community data",
             "External engagement - technology","External engagement - policies","Engagement - Inclusion")

df <- df %>% mutate(Domain = c(as.character((rep("Domain 1", 5))),
                  as.character(rep("Domain 2", 4)),
                  as.character(rep("Domain 3", 6)),
                  as.character(rep("Domain 4", 7))))

And for the ggplot:

df %>% 
ggplot(aes(x = RespondentLevel, y = fct_rev(Question_Code))) +
  geom_tile() +
  theme_minimal(16)

The colours to fill, I'm using:

with each colour corresponding to a domain, and each shade to a level:
Greens <- c("#edf8e9", "#bae4b3", "#74c476", "#31a354", "#006d2c")

Reds <- c("#fee5d9", "#fcae91", "#fb6a4a", "#de2d26", "#a50f15")

Yellows <- c("#ffffeb","#ffff9d","#ffff89", "#ffff4e", "#ffff14")

Blues <- c("#eff3ff","#bdd7e7","#6baed6","#3182bd",  "#08519c")

EDIT: geom_bar also does the trick, but not broken down by gradient. Trying to use this function:

ColourPalleteMulti <- function(df, group, subgroup){

  # Find how many colour categories to create and the number of colours in each
  categories <- aggregate(as.formula(paste(subgroup, group, sep="~" )), df, function(x) length(unique(x)))
  category.start <- (scales::hue_pal(l = 100)(nrow(categories))) # Set the top of the colour pallete
  category.end  <- (scales::hue_pal(l = 40)(nrow(categories))) # set the bottom

  # Build Colour pallette
  colours <- unlist(lapply(1:nrow(categories),
                           function(i){
                             colorRampPalette(colors = c(category.start[i], category.end[i]))(categories[i,2])}))
  return(colours)
}

colours <- ColourPalleteMulti(df, "Domain", "RespondentLevel") 

df %>% 
  ggplot(aes(x = fct_rev(Question_Code), y = RespondentLevel))+
  geom_bar(stat = "identity", aes(fill = Domain), alpha = .9) +
  coord_flip() +
  theme_minimal(16)+
  xlab(" ") +
  ggtitle("Baseline Report Card Sample Community")+
  scale_fill_manual("RespondentLevel", values = colours)+
  theme(legend.title = element_text(size = 14),
        legend.position = "none",
        legend.text = element_text(size = 14),
        plot.title = element_text(size=18, hjust = 0.5),
        plot.caption = element_text(size = 12, hjust = 1),
        axis.text.y = element_text(hjust = 0),
        panel.grid = element_line(colour = "#F0F0F0"),
        plot.margin = unit(c(1,1,0.5,1), "cm"))

Sorry for the long reprex, can adjust if possible

解决方案

Here are a few options for tricks. First off, to get the full set of levels for each question so you don't have gaps in your data, I used tidyr::complete. That's the data frame I'll be working with.

library(ggplot2)
library(dplyr)
library(tidyr)
library(purrr)
library(patchwork)

df_full <- df %>%
  complete(nesting(Domain, Question_Code), RespondentLevel) %>%
  mutate(RespondentLevel = as.character(RespondentLevel)) 

The easier option is to approximate the gradients with changing the alpha, and setting the hue (red, green, etc) based on domain. This forfeits the other colors you've chosen, and just uses the last, darkest color of each palette.

To do this, I made a list of all your palettes. In setting the fill, map_chr(palettes, 5) extracts the 5th element of each list, which is the darkest color of each. You'll probably want to adjust or remove one or both of the legends.

palettes <- list(Greens, Reds, Yellows, Blues)

ggplot(df_full, aes(x = RespondentLevel, y = Question_Code, fill = Domain, alpha = RespondentLevel)) +
  geom_tile() +
  theme_minimal() +
  facet_grid(rows = vars(Domain), scales = "free", space = "free") +
  scale_fill_manual(values = map_chr(palettes, 5))
#> Warning: Using alpha for a discrete variable is not advised.

The more difficult way splits the data by domain and makes a list of plots, then puts them together with the patchwork package. The benefit is that you can keep the full color palettes, but the downside is that it's more difficult to control things like sizing that you get from facet_grid, which adjusts for the fact that there are more questions listed in some domains than in others. You could resize these by hand in plot_layout if you think this approach is worthwhile. You'll also need to adjust some theme elements to mimic what facet_grid would do.

plot_list <- df_full %>%
  split(.$Domain) %>%
  map2(palettes, function(domain_df, pal) {
    ggplot(domain_df, aes(x = RespondentLevel, y = Question_Code, fill = RespondentLevel)) +
      geom_tile() +
      theme_minimal() +
      scale_fill_manual(values = pal) +
      theme(legend.position = "none") +
      labs(x = NULL, y = NULL)
  })

reduce(plot_list, `+`) +
  plot_layout(ncol = 1)

Note that normally, patchwork puts plots together like plot1 + plot2 to mimic ggplot layering. Since I had the plots in a list, I did this with purrr::reduce.

这篇关于按组手动填充多个比例尺的geom_tile的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆