【问题标题】:Colouring specific label in ggplot depending on the value of the id variable on a long data (irrespectively of the row number)根据长数据上 id 变量的值(与行号无关)为 ggplot 中的特定标签着色
【发布时间】:2015-07-14 22:33:58
【问题描述】:

假设我有一个很长的数据集,我想在 x 轴上为特定标签着色。在下面的示例中,我想为 Valiant 的标签着色。

# Packs
require(ggplot2)
require(reshape2)

# Data and trans
data(mtcars)
mtcars$model <- rownames(mtcars)
mtcars <- melt(mtcars, id.vars = "model")

# Some chart
ggplot(data = subset(x = mtcars, subset = mtcars$variable == "cyl"), 
       aes(x = model, y = value)) +
    geom_bar(stat = "identity") +
    theme(axis.text.x = element_text(angle = 90, 
                                     colour =
                                         ifelse(mtcars$model == "Valiant",
                                                "red","black")))

代码生成的下面的图表是错误的,因为错误的标签被着色了。

原因很简单,ifelse 创建的内容与轴上的顺序不匹配。我可以通过强制ggplot 为特定行着色来修复代码。下面的代码为右侧标签着​​色,如用于图表的特定 data.frame 中,Valiant 值为 31 的行。

# Fixed chart
ggplot(data = subset(x = mtcars, subset = mtcars$variable == "cyl"), 
       aes(x = model, y = value)) +
    geom_bar(stat = "identity") +
    theme(axis.text.x = element_text(angle = 90, 
                                     colour =
                                         ifelse(as.numeric(rownames(mtcars)) == 31,
                                                "red","black")))

显然,这种解决方案是极其不切实际的。在实际数据上,我有大量包含多列(地理、性别、指标、价值等)的观察结果。随后通过子集过滤该数据,并将不同的选项传递给aes 设置。试图找出应该着色的行是一场噩梦。我正在寻找一种解决方案,使我能够:

  • 相对轻松地指示要对特定观察进行着色,而无需尝试使用行号
  • 理想情况下,我想使用带有一些字符串的id 来指示我想要突出显示的文本
  • 我想将解决方案封装在ggplot2 代码中,我不想创建单独的数据子集只是为了导出着色向量,因为我将多次这样做。这将不必要地增加对象。
  • 在实践中,我想要这样的解决方案:无论图表上的内容如何,​​当您在 x 轴上找到此字符串时,将其变为红色

【问题讨论】:

    标签: r charts ggplot2 label subset


    【解决方案1】:

    第一个不匹配的原因是 mtcars$model 比您正在绘制的子集长得多,因此颜色向量 ifelse(mtcars$model == "Valiant","red","black") 的长度为 352,但您正在绘制的子集的长度仅为 32。同样的问题您的第二个示例中存在,但在这种情况下,colour 的额外元素(无论如何都是“黑色”)被删除,因此您不会注意到。

    不幸的是,theme(...) 似乎没有使用可用的数据列名进行评估(即不能直接在 theme(...) 调用中执行 colour=ifelse(model == "Valiant", "red", "black")

    另一种方法是将model 设为因子并过滤levels(..) == "Valiant"。如果您有一个长数据框,那么您的 id 变量很可能是一个因素(或者它是一个因素是有意义的)。

    mtcars$model = factor(mtcars$model)
    ggplot(data=subset(mtcars, variable == 'cyl'), aes(x=model, y=value)) +
        geom_bar(stat="identity") +
        theme(axis.text.x=element_text(angle=90,
                  colour=ifelse(levels(mtcars$model) == 'Valiant', 'red', 'black')))
    

    (您的问题源于将subset() 作为您的数据输入ggplot,然后无法在theme 调用中引用该特定子集。我不知道是否有技巧这个)。

    【讨论】:

    • 谢谢,这是一个很好的解决方案。在可用性方面,将第一行和ifelse 语句封装在一个函数中会更容易。我尝试了级别,但我没有想到先在实际列上应用factor
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-09
    • 1970-01-01
    • 2022-01-12
    • 2012-04-07
    • 2012-12-14
    • 2016-11-04
    • 2019-02-16
    相关资源
    最近更新 更多