簡體   English   中英

根據使用 Altair 的特定類別字段的值,沿 Y 軸對整個堆積條形圖進行排序

[英]Sorting a stacked bar chart as a whole along Y-axis, based on the value of a particular category field using Altair

使用文檔中的一個示例,我可以使用 order 對堆疊的條形本身進行order ,但我希望看到沿 Y 軸的整個條形通過site -> Crookston的產量總和進行排序,即藍色條,升序/降序命令。

根據這篇文章,我嘗試使用transform_calculatetransform_join_aggregate ,但它沒有按預期工作。

import altair as alt
from vega_datasets import data

source = data.barley()

alt.Chart(source).mark_bar().transform_calculate(
    key="datum.site == 'Crookston'"
).transform_joinaggregate(
    sort_key="argmax(key)", groupby=['variety']
).transform_calculate(
    sort_val='datum.sort_key.value'  
).encode(
    x=alt.X('sum(yield)', stack='normalize'),
    y=alt.Y('variety', sort=alt.SortField('sort_val', order='ascending')),
    color='site',
    order=alt.Order(
      # Sort the segments of the bars by this field
      'site',
      sort='ascending'
    )
)

在此處輸入圖像描述

預計 Output
沿 Y 軸的條按藍色(站點=Crookston)條的大小排序。

圖表中的每個彩色條代表數據集中所有年份該地點和品種內所有產量的總和。 當您使用argmax時,您是按一年的 Crookston 產量排序,而不是所有年份的 Crookston 總產量。 您可以使用稍微不同的轉換策略來獲得后者:

import altair as alt
from vega_datasets import data

source = data.barley()

alt.Chart(source).mark_bar().transform_calculate(
    filtered="datum.site == 'Crookston' ? datum.yield : 0"
).transform_joinaggregate(
    sort_val="sum(filtered)", groupby=["variety"]
).encode(
    x=alt.X('sum(yield)', stack='normalize'),
    y=alt.Y('variety', sort=alt.SortField('sort_val', order='ascending')),
    color='site',
    order=alt.Order(
      # Sort the segments of the bars by this field
      'site',
      sort='ascending'
    )
)

在此處輸入圖像描述

結果按 Crookston 的總產量正確排序,您可以通過刪除x編碼中的標准化來確認:

alt.Chart(source).mark_bar().transform_calculate(
    filtered="datum.site == 'Crookston' ? datum.yield : 0"
).transform_joinaggregate(
    sort_val="sum(filtered)", groupby=["variety"]
).encode(
    x=alt.X('sum(yield)'),
    y=alt.Y('variety', sort=alt.SortField('sort_val', order='ascending')),
    color='site',
    order=alt.Order(
      'site',
      sort='ascending'
    )
)

在此處輸入圖像描述

如 jakevdp 的回答所示,您可以首先使用計算轉換來定義一個新字段,該字段在站點為“Crookston”時復制產量,否則為 0。 從那里,沒有必要執行 Join Aggregate 轉換; 默認情況下, SortField將直接在 y 軸排序命令中自動對 Crookston 的站點產量求和。

import altair as alt
from vega_datasets import data

source = data.barley()

alt.Chart(source).mark_bar().transform_calculate(
    filtered="datum.site == 'Crookston' ? datum.yield : 0"
).encode(
    x=alt.X("sum(yield)"),
    y=alt.Y(
        "variety",
        sort=alt.SortField("filtered", order="ascending"),
    ),
    color="site",
    order=alt.Order(
        # Sort the segments of the bars by this field
        "site",
        sort="ascending",
    ),
)

結果

實際上,使用transform_joinaggregate的上一個答案的方法通常不能按預期工作,並且僅在此示例中有效,因為源數據集對於每個品種具有完全相同的記錄數。 例如,如果您將產量為 0 的“滿洲”品種的記錄添加到 Crookston 站點,那么該方法現在會將滿洲排序在 y 軸上更遠的兩個位置,低於 Velvet 和 No. 475,高於 No . 462.

source = data.barley()
source = source.append(
    {"yield": 0, "variety": "Manchuria", "site": "Crookston"},
    ignore_index=True,
)

alt.Chart(source).mark_bar().transform_calculate(
    filtered="datum.site == 'Crookston' ? datum.yield : 0"
).transform_joinaggregate(
    sort_val="sum(filtered)", groupby=["variety"]
).encode(
    x=alt.X("sum(yield)"),
    y=alt.Y("variety", sort=alt.SortField("sort_val", order="ascending")),
    color="site",
    order=alt.Order("site", sort="ascending"),
)

結果

從視覺上可以明顯看出,圖表不再按需要排序。 添加零產量不應該影響排序順序; 滿洲里品種在克魯克斯頓的產量仍然低於天鵝絨和 475 號品種。

要查看出了什么問題,您可以在 Vega Editor 中打開第二個代碼塊生成的圖表。 在那里,您將找到一個名為“data_0”的表,其中包含以下條目(不按此順序):

屈服 種類 地點 過濾 排序值
39.93333 《滿洲里》 1931年 “克魯克斯頓” 39.93333 72.9
32.96667 《滿洲里》 1932年 “克魯克斯頓” 32.96667 72.9
0 《滿洲里》 null “克魯克斯頓” 0 72.9
22.56667 《滿洲里》 1932年 “德盧斯” 0 72.9
41.33333 “天鵝絨” 1931年 “克魯克斯頓” 41.33333 73.39999
32.06666 “天鵝絨” 1932年 “克魯克斯頓” 32.06666 73.39999
22.46667 “天鵝絨” 1932年 “德盧斯” 0 73.39999
48.56666 “462號” 1931年 “克魯克斯頓” 48.56666 79.09999

Manchuria 的sort_val為 72.9,比 Velvet 的要少,這是應該的。 但是,Vega 仍然需要確定如何聚合給定品種的每一行中出現的sort_val的重復值。 堆疊圖的默認行為是將其嘗試排序的組中排序字段中的所有條目相加(請參閱: https://vega.github.io/vega-lite/docs/sort.html#sort- by-a-different-field ),這是在第一個代碼塊中派上用場的事實。

源數據集開始時每個品種有 12 個條目。 添加記錄后,滿洲里品種現在有13個條目,所以滿洲里得到的排序值為72.9 · 13=947.7,大於天鵝絨的排序值73.39999 · 12≈880.8,但仍小於462號品種排序值為 79.09999 · 12 ≈ 949.2。 這反映了第二張圖表中的情況。

要解決此問題,您可以指定只使用一個sort_val作為每個品種的排序值,方法是使用EncodingSortField而不是SortField ,並將"min""max""average"作為聚合操作傳遞給op參數,例如sort=alt.EncodingSortField("sort_val", op="min", order="ascending") 或者您可以使用上面的第一種方法並跳過 Join Aggregate 轉換。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM