【问题标题】:Dodged dumbbell plots with ggplot2用 ggplot2 躲避哑铃图
【发布时间】:2021-02-28 10:21:07
【问题描述】:

本题基于this prior question.

考虑以下情节:

Domain = c("A", "B", "C", "D", "E", "F", "G", 
           "A", "B", "C", "D", "E", "F", "G", "A", "B", "C", "D", "E", "F", 
           "G", "A", "B", "C", "D", "E", "F", "G") 

Area = c("State", "State", 
         "State", "State", "State", "State", "State", "National", "National", 
         "National", "National", "National", "National", "National", "State", 
         "State", "State", "State", "State", "State", "State", "National", 
         "National", "National", "National", "National", "National", "National")

race = c("White", "White", "White", "White", "White", "White", 
         "White", "White", "White", "White", "White", "White", "White", 
         "White", "Black", "Black", "Black", "Black", "Black", "Black", 
         "Black", "Black", "Black", "Black", "Black", "Black", "Black", 
         "Black") 

pct_agreement = c(0.557610213756561, 0.735042750835419, 
                  0.567375898361206, 0.633762538433075, 0.64091557264328, 0.750356614589691, 
                  0.564539015293121, 0.651861846446991, 0.697574973106384, 0.653521358966827, 
                  0.713940441608429, 0.680985689163208, 0.751584351062775, 0.642535984516144, 
                  0.488484561443329, 0.581625580787659, 0.456939995288849, 0.580652594566345, 
                  0.630399644374847, 0.711643815040588, 0.347775995731354, 0.627996683120728, 
                  0.668737232685089, 0.610245823860168, 0.690373718738556, 0.705771028995514, 
                  0.738830924034119, 0.550933301448822)

df <- data.frame(Domain, Area, race, pct_agreement)

library(tidyverse)

ggplot(df) +
  geom_point(
    aes(
      x = Domain, y = pct_agreement, color = Area, shape = race,
      group = Area
    ), 
    position = position_dodge(width = 1)
  ) +
  coord_flip()

现在我们想通过连接同一域和区域的每一对点将其变成一个哑铃图。显而易见的代码如下:

df2 <- pivot_wider(df, names_from = race, values_from = pct_agreement)

ggplot(df) +
  geom_point(
    aes(
      x = Domain, y = pct_agreement, color = Area, shape = race,
      group = Area
    ), 
    position = position_dodge(width = 1)
  ) +
  geom_segment(
    data = df2,
    aes(
      x = Domain, xend = Domain, y = White, yend = Black,
      color = Area
    ),
    position = position_dodge(width = 1)
  ) +
  coord_flip()

reprex package (v0.3.0) 于 2019 年 11 月 8 日创建

然而,很明显,这不起作用,因为position_dodge() 并没有避开xend 的审美。我认为这是 ggplot2 中的一个错误,可能应该修复。然而,与此同时,制作这个情节的最简单方法是什么?我可以想到各种方法来做到这一点,但它们似乎都很麻烦。我错过了什么吗?

【问题讨论】:

    标签: r ggplot2


    【解决方案1】:

    我发现嵌套分组通常会导致特定情节的困难。在这些情况下,我发现interaction() 函数非常有用,因为它允许简洁的代码并避免数据重新格式化。我们可以为线段定义一个新的分组。

    重要的是,以下解决方案适用于位置闪避,因为它使用geom_line() 而不是geom_segment()。这避免了position_dodge() 无法处理的xend 美学。

    ggplot(df) +
      geom_point(
        aes(
          x = Domain, y = pct_agreement, color = Area,
          shape = race, group = Area
        ), 
        position = position_dodge(width = 0.5)
      ) +
      geom_line(
        aes(
          x = Domain, y = pct_agreement, color = Area, 
          group = interaction(Area, Domain)
        ),
        position = position_dodge(width = 0.5)
      ) +
      coord_flip()
    

    【讨论】:

      【解决方案2】:

      我会定义我自己的 x 值而不是 dodge:

      df <- data.frame(Domain, Area, race, pct_agreement) %>%
        mutate(myX = as.numeric(Domain) + ifelse(Area == "State", 0.25, -0.25))
      
      df2 <- pivot_wider(df, names_from = race, values_from = pct_agreement)
      
      ggplot(df) +
        geom_point(
          aes(
            x = myX, y = pct_agreement, color = Area, shape = race, group = Area
          )) +
        geom_segment(
          data = df2,
          aes(
            x = myX, xend = myX, y = White, yend = Black, color = Area
          )) +
        # fix the labels
        scale_x_continuous(name = "Domain", breaks = 1:7, labels = LETTERS[1:7]) +
        coord_flip()
      

      也可以混合使用这两种方法并避开点,但使用计算出的 x 值作为线段:

      ggplot(df) +
        geom_point(
          aes(
            x = Domain, y = pct_agreement, color = Area, shape = race,
            group = Area
          ), 
          position = position_dodge(width = 1)
        ) +
        geom_segment(
          data = df2,
          aes(
            x = myX, xend = myX, y = White, yend = Black, color = Area
          )) +
        coord_flip()
      

      reprex package (v0.3.0) 于 2019 年 11 月 8 日创建

      【讨论】:

        【解决方案3】:

        使用哑铃(0.11 版) 一种稍微不同的方法,可能对某些人有用(或可能没用)

        感谢您提出这个具有挑战性的问题。

        ##Reformat data
        w<-df %>% filter(race=='White')
        b<-df %>% filter(race=='Black')
        e<-merge(w,b, by.x=c("Domain","Area"), by.y = c("Domain","Area")) %>% unite("id",Domain,Area, remove = FALSE)
        e$pct_agreement.x<-as.numeric(format(e$pct_agreement.x, digit=3))
        e$pct_agreement.y<-as.numeric(format(e$pct_agreement.y, digit=3))
        
        ##Plot
        dumbbell::dumbbell(e, id="id",key="Area", column1="pct_agreement.x", column2 = "pct_agreement.y", shp="Area", pointsize = 2, pt_val = 1,delt=1, textsize=3, lab1 = "White", lab2="Black") + xlim(.34,.76)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-01-18
          • 2023-03-31
          • 2023-03-20
          相关资源
          最近更新 更多