【问题标题】:plotnine doesn't add legendplotnine 不添加图例
【发布时间】:2020-04-12 17:30:29
【问题描述】:

我正在使用 plotnine 在同一个图中绘制两个图表。 一张图表使用您将在下面看到的数据框中的“b”值,另一张使用“c”中的值。

我只需要显示一个简单的图例图例,在其中我可以看到带有相应颜色的“c”和“b”。

def plot_log_detected():
    df = DataFrame({'x': [1, 2, 3, 4, 5],
                    'b': >>>SOME VALUES DOESNT MATTER<<<,
                    'c': >>>SOME VALUES DOESNT MATTER<<<
                   })
    return ggplot(aes(x='x', y='b'), data=df) + geom_point(size=1) +\
           geom_line(aes(y='b'), color='black') + \
           geom_line(aes(y='c'), color='blue') +  \
           ggtitle("TITLE") + \
           labs(y="Y AXIS", x="X AXIS")

【问题讨论】:

  • 当您发布问题时,请尝试确保您的示例可运行。在这种情况下,您将包含一些虚构的数字,而不是 &gt;&gt;&gt;SOME VALUES DOESNT MATTER&lt;&lt;&lt;。这样一来,其他人就可以轻松地以您为榜样,直接关注问题,而不是编造数据。

标签: python ggplot2 python-ggplot plotnine


【解决方案1】:

如果您在R 中使用ggplot2,这将不会显示图例:仅当您在geom 的美学中指定color= 时,才会显示颜色图例。对于rpythonggplot 中的“修复”是相同的。您需要组织数据,以便遵循tidy data 原则。在这种情况下,df$bdf$c 列各包含两条信息:(1) "y" 的 value 和 (2) "y" 的 type .您应该相应地重新组织数据,以便您的列名变为:xtype_of_yvalue_of_y

我将通过填写您提供的数据集进行解释,然后说明我们如何将其更改为整洁的格式,然后您如何(正确)应用代码来表示我相信您想要的情节。

基础知识

这是一个数据集和一个像你的情节一样的情节(同样,它在r...所以我希望你能翻译成python):

df <- data.frame(
    x=c(1:5), b=c(10, 12, 14, 9, 8), c=c(9, 11, 11, 12, 14))

ggplot(df, aes(x=x)) +
    geom_line(aes(y=b), color='red') +
    geom_line(aes(y=c), color='blue')

没有传说,但颜色就在那里,我们绘制出您所期望的。这里的问题是ggplotaes() 调用中指定颜色时会绘制一个图例。 为了清楚地看到这一点,让我们做同样的图,但将color=... 移动到@987654349 中@:

ggplot(df, aes(x=x)) +
    geom_line(aes(y=b, color='red')) +
    geom_line(aes(y=c, color='blue'))

好吧……等等。什么?它现在有一个图例(因为我们把 color inside aes()),但是颜色实际上是按顺序颠倒的......你会注意到颜色不是红色和蓝色,而是ggplot2 的默认“红色”和“青色”颜色。实际上,发生的事情是我们只指定在第一个geom_line 调用中,我们绘制了正确的数据集,但我们只是将数据“命名”为“红色”。同样,我们将另一个数据集“命名”为“蓝色”。 ggplot 根据默认调色板决定使用什么颜色。

无需整理数据即可获得传奇

如果您不想弄乱您的数据,实际上有一种方法可以做到这一点,并且可能会获得您可能会满意的输出。我们只需要在color= 中指明您要调用该系列的名称

ggplot(df, aes(x=x)) +
    geom_line(aes(y=b, color='b')) +
    geom_line(aes(y=c, color='c'))

添加另一个color='blue' 以在aes()外部以及内部获得“蓝色”颜色怎么样?嗯……这行不通。例如,如果您这样做,结果与显示的原始图相同(没有图例,但颜色值正确),因为 aes() 在每个 geom_line 调用中被有效地覆盖:

# this doesn't work to keep legend and desired color, the second
# color outside aes() overwrites the one inside aes()
ggplot(df, aes(x=x)) +
    geom_line(aes(y=b, color='b'), color='red') +
    geom_line(aes(y=c, color='c'), color='blue')

整洁的数据方式(“正确”方式)

虽然上述方法有效,但它违反了整理数据的一般原则以及如何组织数据以便易于分析......以任何你想要的方式。相信我:这绝对是使用任何数据集进行多功能分析的最佳实践,并且几乎总是值得付出努力以这种方式组织数据。

ggplot 想要您将aes() 参数指定为数据集中的列。这意味着我们应该让每一列在您的数据集中都有特定的用途:

  • x: 这与原始数据集中的 x 相同。它只代表x轴值

  • type_of_y:此列包含值“b”或“c”,指示值应来自哪个数据系列。

  • value_of_y:此列包含您将在 y 上绘制的值。

使用dplyr,我们可以非常简单地以这种方式重新组织数据:

df <- df %>% gather('type_of_y', 'value_of_y', -x)

给你:

   x type_of_y value_of_y
1  1         b         10
2  2         b         12
3  3         b         14
4  4         b          9
5  5         b          8
6  1         c          9
7  2         c         11
8  3         c         11
9  4         c         12
10 5         c         14

然后您相应地绘制,仅使用一个geom_line 调用并将color 美学应用于type_of_y。像这样的:

ggplot(df, aes(x=x, y=value_of_y)) +
    geom_line(aes(color=type_of_y))

这样,您只需指定一个geom_line 调用。在这里可能看起来并没有太大的不同,但是如果您的原始数据集中有多个列怎么办?例如,有“x”,然后是“a”、“b”、“c”...“z”的 y 值!您必须在对geom_line 的单独调用中指定所有这些行!在上述情况下,无论您有多少个不同的 y 值列……您只有相同的两行代码,并且只有一次调用 geom_line。有道理?有关更多信息,我会建议上面的链接。另外,this article 是一本不错的读物。

然后,您可以通过添加 scale_color_manual 并以这种方式指定颜色来指定特定的颜色(还有其他一些方法) - 但如果您需要帮助,我会在单独的问题中提问。另外...不确定python 的代码有何不同。同样,您可以通过labs(color="your new legend title")... 更改图例标题以及其他主题更改。

我知道它与 python 中的代码不太一样,但这应该足以让您了解我们如何在此处进行类似操作。

【讨论】:

  • 我不太了解第一行,我确实在 aes 中使用 color= 作为 geom,还有整洁的数据部分(我很快阅读)是对我来说有点困惑,让我们以 df['b'] 为例,重组 x 中的数据是什么意思,将它分成 type_of_y 和 value_of_y 是什么意思,(我认为解释它的最好方法对我来说将是一个非常简短的代表 DataFrame 的示例),也感谢您努力回答这个问题,尽管您使用 R :)
  • 我刚刚用一个完整的例子对原始答案进行了重要的编辑。希望这能准确解释如何调整数据并使用整洁的数据绘制“正确”的方式。话虽如此,仍然可以通过对原始代码进行微小更改来获得正确的图例,但这是一种不好的做法,并且当原始数据中有许多不同的数据系列时会变得非常尴尬和重复。再次......是的,它不是 python,但你的问题实际上是在处理 ggplot 的原则,这对我们所有人来说应该是普遍的 :)
  • 在 python 中,它给了我错误 plotnine.exceptions.PlotnineError: "Could not evaluate the 'color' mapping: 'c' (original error: name 'c' is not defined)" 当我在 aes 中指定任何颜色。
【解决方案2】:

您可以融合数据框以将“b”列和“c”列合并为一列,并创建一个美学列“颜色”用于着色和图例。这是代码和输出。请注意,我将原始数据框用于点图(因为您只在其中绘制了“b”列)并将融化的数据框用于线图:

def plot_log_detected():
    df = DataFrame({'x': [1, 2, 3, 4, 5],
                    'b': [1, 2, 3, 4, 5],
                    'c': [1, 3, 2, 5, 4]
                   })

    df_melt = df.melt(id_vars=['x'], value_vars=['b','c'], var_name='color', value_name='b_and_c')

    return ggplot(aes(x='x', y='b'), data=df) + geom_point(size=1) +\
           geom_line(aes(y='b_and_c', color='color'), data=df_melt) + \
           ggtitle("TITLE") + \
           labs(y="Y AXIS", x="X AXIS")

您的原始示例数据框如下所示:

   x  b  c
0  1  1  1
1  2  2  3
2  3  3  2
3  4  4  5
4  5  5  4

你融化的数据框是:

   x color  b_and_c
0  1     b        1
1  2     b        2
2  3     b        3
3  4     b        4
4  5     b        5
5  1     c        1
6  2     c        3
7  3     c        2
8  4     c        5
9  5     c        4

最后这是输出图像:

【讨论】:

    【解决方案3】:
    def plot_log_detected():
        df = DataFrame({'x': [1, 2, 3, 4, 5],
                        'b': >>>SOME VALUES DOESNT MATTER<<<,
                        'c': >>>SOME VALUES DOESNT MATTER<<<
                       })
        plot = (
            ggplot(aes(x='x', y='b'), data=df) 
            + geom_point(size=1)
            + geom_line(aes(y='b', color='"black"')) # Put color in double quotes
            + geom_line(aes(y='c', color='"blue"'))  # Put color in double quotes
            + ggtitle("TITLE")
            + labs(y="Y AXIS", x="X AXIS")
            
            # Add color scale identity
            + scale_color_identity(
                guide='legend', 
                breaks=['black', 'blue'], 
                labels=['Label for black', 'Label for blue']))
        return plot
    

    【讨论】:

    • 虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。
    【解决方案4】:

    我有另一个解决方案,我使用melt将宽数据格式转换为长数据格式。为了生成图例,我们需要为美学映射提供一个分组列,因此使用 melt 我们可以创建一个列标签类别并将其传递给 plotnine 颜色参数。

    def plot_log_detected():
        df = DataFrame({'x': [1, 2, 3, 4, 5],
                        'b': [22,33,21,66,55],
                        'c': [44,11,22,77,55]
                       })
    
        long_data = pd.melt(df, id_vars=["x"], value_vars=["b", "c"])
        long_data = long_data.rename(columns = {'variable':'category'})
    
        return ggplot(aes(x='x', y='value', color = "category"), data=long_data) +\
               geom_point(size=1) +\
               geom_line() + \
               ggtitle("TITLE") + \
               labs(y="Y AXIS", x="X AXIS")
    
    plot_log_detected()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多