【问题标题】:Stacked text in a stacked area chart using Altair使用 Altair 在堆积面积图中堆积文本
【发布时间】:2020-06-24 18:09:50
【问题描述】:

我想知道是否可以在堆积面积图的相应区域中使用文本标记。

我使用 median 聚合来获取单个 X 和 Y 轴值,否则它会显示整个图表边缘的文本。不过这个聚合也不是万无一失的,好像图表有点复杂,那么X轴位置可能不是文本显示的最佳区域。

据我所知-

X=[1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9]
V=[1,1,1,2,4,8,6,4,2,1,2,3,4,5,6,7,6,5,1,1,1,1,4,8,4,2,1,1,1,3,4,5,6,6,5,4]
key=['a', 'b', 'c', 'd']
K = [y for x in key for y in (x)*9]

demo = pd.DataFrame({'X': X, 'V': V, 'K': K})
a = alt.Chart(demo).mark_area().encode(
    x='X:O',
    y='V:Q',
    color='K:N'
)
t = alt.Chart(demo).mark_text().encode(
    x='median(X):O',
    y='median(V):Q',
    text=alt.Text('K:N',)
)
a+t

问题

  • 文本不在正确的区域。
  • 文字顺序也错了。

并不是我不明白为什么我会遇到这些问题,我实际上是这样做的(Y 位置没有聚合为“堆叠”在彼此之上),但我不知道如何解决或者是否解决现在甚至是可行的。

【问题讨论】:

    标签: python data-visualization altair vega-lite vega


    【解决方案1】:

    我将为文本构建一个单独的数据框并将其用作源。如果在这种情况下甚至可以实现,那么它比在 Altair 中进行各种转换更容易且可定制。

    import pandas as pd
    import altair as alt
    
    X=[1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9]
    V=[1,1,1,2,4,8,6,4,2,1,2,3,4,5,6,7,6,5,1,1,1,1,4,8,4,2,1,1,1,3,4,5,6,6,5,4]
    key=['a', 'b', 'c', 'd']
    K = [y for x in key for y in (x)*9]
    
    demo = pd.DataFrame({'X': X, 'V': V, 'K': K})
    
    # find X position where the sum of V's of K's is the maximum (this is at X=6)
    idxmax = demo.groupby(["X"]).sum().idxmax()[0]
    # find the cumulative sum of V's at position idxmax and
    # take away some offset (4) so the labels go down a bit
    # iloc[::-1] reverses the order because we want cumulative to start from the bottom (from 'd')
    ypos = demo.groupby(["X", "K"]).sum().loc[idxmax].iloc[::-1].cumsum()["V"] - 4
    # crate a new dataframe for the text, X column=idmax, Y column=cumulative ypos, K=key
    demotext = pd.DataFrame([[idxmax, y, k] for y,k in zip(ypos.tolist(), key[::-1])],
                            columns=["X", "Y", "K"])
    
    
    a = (alt.Chart(demo).mark_area()
            .encode(
                    x='X:O',
                    y='V:Q',
                    color='K:N')
        )
    t = (alt.Chart(demotext).mark_text()
            .encode(
                    x='X:O',
                    y='Y:Q',
                    text='K:N'
    ))
    
    a+t
    

    输出

    【讨论】:

    • 看看你是否可以通过不从 Y 中删除一个固定值(在本例中为 4)但将每个文本居中在其相应区域的中间来改进它。例如,'a' 和 'c' 没有很好地居中。
    • 我也想了很久很久,我想你可能是对的。 Altair 或 Vega-Lite 无法在内部执行此操作,而且可能不会有。需要使用不同的文本数据集手动完成。
    • 当图表的峰值没有很好地对齐时,事情会变得相当复杂。我想我也会为此写下我自己的答案,但请接受你的。
    【解决方案2】:

    我开始意识到,可能无法以编程方式执行此操作,或者由于涉及的复杂性(例如未对齐的峰),它可能不值得。 修改上面给出的数据稍微突出了这个问题-

    import pandas as pd
    import altair as alt
    
    X=[1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9]
    V=[1,1,1,2,4,8,6,4,2,1,2,3,4,5,6,7,6,5,1,1,1,1,4,8,4,2,1,1,5,9,5,3,1,1,1,1]
    key=['a', 'b', 'c', 'd']
    K = [y for x in key for y in (x)*9]
    
    demo = pd.DataFrame({'X': X, 'V': V, 'K': K})
    
    # get the x and y positions for max values of the graph
    demo.groupby('K').max()
    
    # crate a new dataframe for the text, X column=idmax, Y column=cumulative ypos, K=key
    demotext = pd.DataFrame([[idxmax, y, k] for y,k in zip(ypos.tolist(), key[::-1])],
                            columns=["X", "Y", "K"])
    
    
    a = (alt.Chart(demo).mark_area()
            .encode(
                    x='X:O',
                    y='V:Q',
                    color='K:N')
        )
    t = (alt.Chart(demotext).mark_text()
            .encode(
                    x='X:O',
                    y='Y:Q',
                    text='K:N'
    ))
    a+t
    

    如果您有一个非常复杂的图表,我认为最好和最简单的方法是手动构建文本数据 -

    a = (alt.Chart(demo).mark_area()
            .encode(
                    x='X:O',
                    y='V:Q',
                    color='K:N')
        )
    t = (alt.Chart(p).mark_text()
            .encode(
                    x='X:O',
                    y='csum:Q',
                    text='K:N'
    ))
    a+t
    

    p 在哪里 -

        K   V   X   csum
    0   a   8   6   18
    1   b   7   7   7
    2   c   8   6   4
    3   d   9   3   4
    

    【讨论】:

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