【问题标题】:bicolor heatmap with factor levels具有因子水平的双色热图
【发布时间】:2019-11-13 06:03:41
【问题描述】:

我有这个数据框:

set.seed(0)
df <- data.frame(id = factor(sample(1:100, 10000, replace=TRUE), levels=1:100),
          year = factor(sample(1950:2019, 10000, replace=TRUE), levels=1950:2019)) %>% unique() %>% arrange(id, year)

我正在寻找一个热图,其中 id 在 X 轴上,年份在 Y 轴上,当数据点存在时颜色为蓝色,当数据不存在时颜色为红色'不存在。我快到了,但我不知道要更改两种颜色的填充参数:

ggplot(df, aes(id, year, fill= year)) + 
  geom_tile()

将这两个变量绘制为因子的目的是即使在某些年份没有任何 id 时也绘制它们(并将其整行绘制为红色)。

编辑

有两件事我忘了补充(希望还不算太晚):

  • 如何在不弄乱geom_tile() 的情况下添加alpha 透明度?
  • 我需要将 id 从最大缺失到最小缺失排序。

【问题讨论】:

    标签: r ggplot2 dplyr tidyverse


    【解决方案1】:

    tidyr 包中的complete() 函数可用于填充缺失的组合。首先,您需要设置一个标志变量来指示数据是否存在,然后用缺失的组合展开数据框,并用 0 填充新的标志变量:

    df <- df %>% 
      mutate(flag = TRUE) %>% 
      complete(id, year, fill = list(flag = FALSE))
    
    ggplot(df, aes(id, year, fill = flag)) + 
      geom_tile()
    

    EDIT1:要添加透明度,请在geom_tile() 中添加alpha = 0.x,其中x 是指示透明度的值。值越低,越透明。

    EDIT2:要按缺失进行排序,请在 ggplot 代码之前添加以下代码:

    # Determine the order of the IDs
    df_order <- df %>% 
      group_by(id) %>% 
      summarize(sum = sum(flag)) %>% 
      arrange(desc(sum)) %>% 
      mutate(order = row_number()) %>% 
      select(id, order)
    
    # Set the IDs in order on the chart
    df <- df %>% 
      left_join(df_order) %>% 
      mutate(id = fct_reorder(id, order))
    

    【讨论】:

    • 太棒了!有什么办法可以排序吗?例如,从 FALSE 的最大到最小计数对 id 进行排序?我在complete() 函数之后尝试了arrange(),但似乎我必须更改因子水平顺序才能做到这一点,有没有更简单的方法?此外,你能解释一下 R 在fill=list(flag=FALSE) 中是如何思考/工作的吗?为什么一定要转成列表?
    • @Chris,显示的数据只有 1 和 0。如果您想查看每个 id 有多少,请使用 df %&gt;% group_by(id) %&gt;% summarize(sum = sum(flag))
    • @Chris complete() 需要fill 参数的列表,因为可能有多个变量需要输入默认值而不是NA
    • 感谢您回答@Phil!。我遇到的主要问题是如何在代码中集成df %&gt;% group_by(id) %&gt;% summarize(sum = sum(flag)) 而无需将另一个对象分配给变量?假设我总是尝试像示例一样在一次性代码中进行绘图(以节省内存并瞄准干净的代码)
    • @Chris 我已经编辑了上面的答案以回答其他 2 个问题。
    【解决方案2】:

    我认为您需要在绘图之前进行一些预处理。创建一个临时变量 (data_exist),它表示存在 idyear 的数据。然后使用complete 为每个id 填充缺失的years 并绘制它。

    library(tidyverse)
    df %>%
       mutate_all(~as.integer(as.character(.))) %>%
       mutate(data_exist = 1) %>%
       complete(id, year = min(year):max(year), fill = list(data_exist = 0)) %>%
       mutate(data_exist = factor(data_exist)) %>%
       ggplot() + aes(id, year, fill= data_exist) + geom_tile()
    

    【讨论】:

      【解决方案3】:

      使用expand.grid您可以创建一个包含所有 id 和年份组合的数据框,然后加入此组合以查看您是否在 df 中拥有它们

        all <- expand.grid(id=levels(df$id),year=levels(df$year)) %>% 
                    left_join(df) %>% 
                    mutate(present=ifelse(is.na(present),'0','1'))
         ggplot(all, aes(as.numeric(id), as.numeric(year), fill= present)) + 
                  geom_tile() + 
                  scale_fill_manual(values=c('0'='red','1'='blue')) + # change default colors
                  theme(legend.position="None") # hide legend
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-30
        • 2020-07-11
        • 1970-01-01
        • 2019-08-06
        • 2015-12-22
        • 1970-01-01
        • 1970-01-01
        • 2016-12-24
        相关资源
        最近更新 更多