代码之家  ›  专栏  ›  技术社区  ›  jakes

如何删除堆叠几何图形列之间的空白

  •  4
  • jakes  · 技术社区  · 7 年前
    library(tidyverse)
    library(lubridate)
    
    date <- seq(ymd('2018-08-01'), ymd('2018-08-31'), by = '1 day')
    c <- 21.30
    x1 <- runif(length(date), 0, 20)
    x2 <- rnorm(length(date), 10, 3)
    x3 <- abs(rnorm(length(date), 40, 10))
    data <- data.frame(c, x1, x2, x3) %>% 
      t() %>% as.data.frame() %>% rownames_to_column('var')
    data <- data %>%
      mutate(category1 = c('catA', 'catB', 'catB', 'catC') %>% as.factor(),
             category2 = c('catAA', 'catBA', 'catBB', 'catCA') %>% as.factor())
    names(data) <- c('var', as.character(date), 'category1', 'category2')
    data_long <- data %>% 
      gather(date, value, -var, -category1, -category2) %>% 
      mutate(date = ymd(date))
    
    data_long %>%
      ggplot(aes(date, value, fill = category1)) +
      geom_col(position = 'stack') +
      scale_x_date(breaks = '1 week', date_labels = '%Y-%m-%d', expand = c(.01, .01)) +
      theme_minimal() +
      theme(axis.text.x = element_text(angle = 90, vjust = .4)) +
      labs(fill = '')
    

    通过上面的示例数据和代码,我生成以下绘图: enter image description here

    我需要做的是删除列之间的空白。我发现了一些类似的话题,但他们建议使用 position_dodge() position = 'stack' ,无法替换。那我怎样才能使这两列相邻呢?

    编辑

    设置 width = 1

    data_long %>%
      mutate(date = floor_date(date, unit = 'week', week_start = 1)) %>% 
      group_by(category1, date) %>% 
      summarise(value = sum(value, na.rm = TRUE)) %>% 
      ungroup() %>% 
      ggplot(aes(date, value, fill = category1, width = 1)) +
      geom_col(position = 'stack') +
      scale_x_date(breaks = '1 month', date_labels = '%Y-%m', expand = c(.01, .01)) +
      theme_minimal() +
      theme(axis.text.x = element_text(angle = 90, vjust = .4)) +
      labs(fill = '')
    

    enter image description here

    编辑2。

    正如@Camille所指出的,如果是日期刻度,1的宽度可能是指1天。但是,以下操作不会产生预期的输出并返回警告消息: position_stack requires non-overlapping x intervals

     data_long %>%
        mutate(date = floor_date(date, unit = 'month', week_start = 1)) %>% 
        group_by(category1, date) %>% 
        summarise(value = sum(value, na.rm = TRUE),
                  n = n()) %>% 
        ungroup() %>% 
        ggplot(aes(date, value, fill = category1, width = n)) +
        geom_col(position = 'stack') +
        scale_x_date(breaks = '1 month', date_labels = '%Y-%m', expand = c(.01, .01)) +
        theme_minimal() +
        theme(axis.text.x = element_text(angle = 90, vjust = .4)) +
        labs(fill = '')
    

    enter image description here

    2 回复  |  直到 7 年前
        1
  •  5
  •   camille    7 年前

    的文档 geom_col 比我在上面的评论更具体。宽度参数的更详细含义:

    钢筋宽度。默认情况下,设置为数据分辨率的90%。

    我降低α值只是为了看看条是否重叠。

    因此,在不设置宽度的情况下,默认值为观测之间距离的90%,即一周的90%。

    library(tidyverse)
    library(lubridate)
    ...
    
    summarized <- data_long %>%
      mutate(date = floor_date(date, unit = 'week', week_start = 1)) %>% 
      group_by(category1, date) %>% 
      summarise(value = sum(value, na.rm = TRUE)) %>% 
      ungroup()
    
    ggplot(summarized, aes(date, value, fill = category1)) +
      geom_col(alpha = 0.6) +
      scale_x_date(breaks = '1 week', expand = c(.01, .01))
    

    将width设置为1表示宽度为1天。我觉得这里有一个差异,其他人可能可以解释,为什么这是读为1天,而不是100%的决议。

    ggplot(summarized, aes(date, value, fill = category1)) +
      geom_col(alpha = 0.6, width = 1) +
      scale_x_date(breaks = '1 week', expand = c(.01, .01))
    

    ggplot(summarized, aes(date, value, fill = category1)) +
      geom_col(alpha = 0.6, width = 7) +
      scale_x_date(breaks = '1 week', expand = c(.01, .01))
    

    编辑: link in my comment ,最好的方法可能只是将日期转换为字符串,这样您就可以像正常情况一样在离散的x刻度上绘图。在你打电话之前 as.character ,你可以做任何你想做的格式化。

    summarized %>%
      mutate(date = as.character(date)) %>%
      ggplot(aes(x = date, y = value, fill = category1)) +
        geom_col(width = 1)
    

        2
  •  4
  •   Jon Spring    7 年前

    (顺便说一句,包括 set.seed() set.seed(42) 为了这些。)

    geom_rect geom_tile 而不是 geom_col . 然后,你可以使每个酒吧完全一样多天/周/月你想要的宽度。但这需要更多的准备工作。

    padr::pad 或者其他一些东西来自动直觉地知道增量应该是多少。)

    data_long2 <- data_long %>%
      group_by(date) %>%
      arrange(desc(category2)) %>%
      mutate(top = cumsum(value),
             bottom = top - value) %>%
      ungroup() %>%
      group_by(category2) %>%
      mutate(next_date = lead(date, default = max(date) + 1)) %>%
      ungroup()
    

    地砖 去拿你的图表。它们是可以互换的,但它们使用不同的坐标系,分别基于角点或中心。

    下面是一个使用

    ggplot(data_long2) +
      geom_rect(aes(xmin = date, xmax = next_date,
                    ymin = bottom, ymax = top,
                    fill = category1)) +
      scale_x_date(breaks = '1 week', date_labels = '%Y-%m-%d', expand = c(.01, .01)) +
      theme_minimal() +
      theme(axis.text.x = element_text(angle = 90, vjust = .4)) +
      labs(fill = '', y = "")
    

    enter image description here

    或者你可以用 地砖 ,在这个例子中,我在每个小节的中间对齐日期。

    ggplot(data_long2) +
      geom_tile(aes(x = date, width = as.numeric(next_date - date),
                    y = (top + bottom)/2, height = (top - bottom),
                    fill = category1)) +
      scale_x_date(breaks = '1 week', date_labels = '%Y-%m-%d', expand = c(.01, .01)) +
      theme_minimal() +
      theme(axis.text.x = element_text(angle = 90, vjust = .4)) +
      labs(fill = '')
    

    enter image description here