Altair 中排序条形图层与标记圆排序层的连接问题

Concatenation issue of sorted bar chart layer with mark circle sorted layer in Altair

我正在尝试在 Altair 中连接两个排序层。当我这样做时,它会添加额外的刻度标签。

我试过缩放解析,轴=None,但它不起作用。

此外,这个问题看起来与 https://github.com/altair-viz/altair/issues/820 and https://github.com/vega/vega-lite/issues/3710 有关,但我未能根据这些线程解决我的问题。

我的代码如下。我 运行 它在 Colab Altair 4.2.0 中。

base = alt.Chart(df_viz2)

bar = base.mark_bar().encode(
    y = alt.Y(field='region_name', type='nominal',  title=None, 
              sort=alt.Sort(
                  field = 'sirens_duration', 
                  op = 'mean', 
                  order='descending'),
              axis = alt.Axis(
                  offset=80
                  ,grid=False
                  ,domain=False
                  ,ticks=False
              )
            )
    ,x = alt.X(field='sirens_duration', aggregate = 'mean', 
               axis = alt.Axis(
                  orient='top', 
                  grid=False, 
                  domain=False, 
                  labels=False,
                  ticks=False, 
                  title='Сумарна тривалість', 
                  titleAlign='right', 
                  titleX=100,
                  titleFontWeight='lighter'
                 ) 
    )
    ,color = alt.condition(
        alt.datum.region_name == 'Луганська',
        alt.value('#60bdb7'),
        alt.value('black')
    )
)

bar_text = bar.mark_text(align='left', baseline='middle', dx=4, fontSize = 14).encode(
    text = alt.Text(field = 'sirens_dur_days_in_ua', type = 'nominal'))


bubble = base.mark_circle(color='black', align='right').encode(
    y = alt.Y(field='region_name', type='nominal', sort=alt.Sort(field='sirens_duration',  order='descending'), 
              title=None, 
              axis = alt.Axis(
                          grid=False, 
                          domain=False, 
                          labels=False,
                          ticks=False)
             )
    ,size = alt.Size('sirens_count', legend=None)
  )

alt.layer(bar, bar_text, bubble).configure_view(
    strokeWidth = 0).properties(
        width = 400, height = 500).configure_axis(
    labelFontSize=16
    ,labelFont='Calibri'
).configure_axisX(
    titleFontSize=10
).resolve_scale(
    y='independent'
)

我的目标是模仿下面的数据可视化

JSON 中的数据以重现图表

{
"0": {
    "region": "\u041b\u0443\u0433\u0430\u043d\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 53.1119097222,
    "sirens_count": 3,
    "region_name": "\u041b\u0443\u0433\u0430\u043d\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "53 days 02:41:09",
    "sirens_dur_days_in_ua": "53 \u0434. 02 \u0433\u043e\u0434. 41 \u0445\u0432.",
    "sirens_duration_sec": 4588869.0
},
"1": {
    "region": "\u0425\u0430\u0440\u043a\u0456\u0432\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 16.9388541667,
    "sirens_count": 544,
    "region_name": "\u0425\u0430\u0440\u043a\u0456\u0432\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "16 days 22:31:57",
    "sirens_dur_days_in_ua": "16 \u0434. 22 \u0433\u043e\u0434. 31 \u0445\u0432.",
    "sirens_duration_sec": 1463517.0
},
"2": {
    "region": "\u041a\u0438\u0457\u0432",
    "sirens_duration": 14.7969444444,
    "sirens_count": 359,
    "region_name": "\u041a\u0438\u0457\u0432",
    "sirens_dur_days": "14 days 19:07:36",
    "sirens_dur_days_in_ua": "14 \u0434. 19 \u0433\u043e\u0434. 07 \u0445\u0432.",
    "sirens_duration_sec": 1278456.0
},
"3": {
    "region": "\u0416\u0438\u0442\u043e\u043c\u0438\u0440\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 13.8627430556,
    "sirens_count": 315,
    "region_name": "\u0416\u0438\u0442\u043e\u043c\u0438\u0440\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "13 days 20:42:21",
    "sirens_dur_days_in_ua": "13 \u0434. 20 \u0433\u043e\u0434. 42 \u0445\u0432.",
    "sirens_duration_sec": 1197741.0
},
"4": {
    "region": "\u0417\u0430\u043f\u043e\u0440\u0456\u0437\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 11.8004861111,
    "sirens_count": 293,
    "region_name": "\u0417\u0430\u043f\u043e\u0440\u0456\u0437\u044c\u043a\u0430",
    "sirens_dur_days": "11 days 19:12:42",
    "sirens_dur_days_in_ua": "11 \u0434. 19 \u0433\u043e\u0434. 12 \u0445\u0432.",
    "sirens_duration_sec": 1019562.0
},
"5": {
    "region": "\u0414\u043d\u0456\u043f\u0440\u043e\u043f\u0435\u0442\u0440\u043e\u0432\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 11.3181018519,
    "sirens_count": 357,
    "region_name": "\u0414\u043d\u0456\u043f\u0440\u043e\u043f\u0435\u0442\u0440\u043e\u0432\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "11 days 07:38:04",
    "sirens_dur_days_in_ua": "11 \u0434. 07 \u0433\u043e\u0434. 38 \u0445\u0432.",
    "sirens_duration_sec": 977884.0
},
"6": {
    "region": "\u041f\u043e\u043b\u0442\u0430\u0432\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 11.2759953704,
    "sirens_count": 304,
    "region_name": "\u041f\u043e\u043b\u0442\u0430\u0432\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "11 days 06:37:26",
    "sirens_dur_days_in_ua": "11 \u0434. 06 \u0433\u043e\u0434. 37 \u0445\u0432.",
    "sirens_duration_sec": 974246.0
},
"7": {
    "region": "\u0427\u0435\u0440\u043a\u0430\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 10.9991550926,
    "sirens_count": 284,
    "region_name": "\u0427\u0435\u0440\u043a\u0430\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "10 days 23:58:47",
    "sirens_dur_days_in_ua": "10 \u0434. 23 \u0433\u043e\u0434. 58 \u0445\u0432.",
    "sirens_duration_sec": 950327.0
},
"8": {
    "region": "\u0414\u043e\u043d\u0435\u0446\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 10.1539583333,
    "sirens_count": 323,
    "region_name": "\u0414\u043e\u043d\u0435\u0446\u044c\u043a\u0430",
    "sirens_dur_days": "10 days 03:41:42",
    "sirens_dur_days_in_ua": "10 \u0434. 03 \u0433\u043e\u0434. 41 \u0445\u0432.",
    "sirens_duration_sec": 877302.0
},
"9": {
    "region": "\u0427\u0435\u0440\u043d\u0456\u0433\u0456\u0432\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 9.9871180556,
    "sirens_count": 276,
    "region_name": "\u0427\u0435\u0440\u043d\u0456\u0433\u0456\u0432\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "9 days 23:41:27",
    "sirens_dur_days_in_ua": "9 \u0434. 23 \u0433\u043e\u0434. 41 \u0445\u0432.",
    "sirens_duration_sec": 862887.0
},
"10": {
    "region": "\u041c\u0438\u043a\u043e\u043b\u0430\u0457\u0432\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 9.5389467593,
    "sirens_count": 213,
    "region_name": "\u041c\u0438\u043a\u043e\u043b\u0430\u0457\u0432\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "9 days 12:56:05",
    "sirens_dur_days_in_ua": "9 \u0434. 12 \u0433\u043e\u0434. 56 \u0445\u0432.",
    "sirens_duration_sec": 824165.0
},
"11": {
    "region": "\u041a\u0438\u0457\u0432\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 9.5028472222,
    "sirens_count": 213,
    "region_name": "\u041a\u0438\u0457\u0432\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "9 days 12:04:06",
    "sirens_dur_days_in_ua": "9 \u0434. 12 \u0433\u043e\u0434. 04 \u0445\u0432.",
    "sirens_duration_sec": 821046.0
},
"12": {
    "region": "\u0421\u0443\u043c\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 8.9156712963,
    "sirens_count": 207,
    "region_name": "\u0421\u0443\u043c\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "8 days 21:58:34",
    "sirens_dur_days_in_ua": "8 \u0434. 21 \u0433\u043e\u0434. 58 \u0445\u0432.",
    "sirens_duration_sec": 770314.0
},
"13": {
    "region": "\u041a\u0456\u0440\u043e\u0432\u043e\u0433\u0440\u0430\u0434\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 8.4262152778,
    "sirens_count": 215,
    "region_name": "\u041a\u0456\u0440\u043e\u0432\u043e\u0433\u0440\u0430\u0434\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "8 days 10:13:45",
    "sirens_dur_days_in_ua": "8 \u0434. 10 \u0433\u043e\u0434. 13 \u0445\u0432.",
    "sirens_duration_sec": 728025.0
},
"14": {
    "region": "\u0412\u0456\u043d\u043d\u0438\u0446\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 8.3401967593,
    "sirens_count": 253,
    "region_name": "\u0412\u0456\u043d\u043d\u0438\u0446\u044c\u043a\u0430",
    "sirens_dur_days": "8 days 08:09:53",
    "sirens_dur_days_in_ua": "8 \u0434. 08 \u0433\u043e\u0434. 09 \u0445\u0432.",
    "sirens_duration_sec": 720593.0
},
"15": {
    "region": "\u041e\u0434\u0435\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 6.6181944444,
    "sirens_count": 184,
    "region_name": "\u041e\u0434\u0435\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "6 days 14:50:12",
    "sirens_dur_days_in_ua": "6 \u0434. 14 \u0433\u043e\u0434. 50 \u0445\u0432.",
    "sirens_duration_sec": 571812.0
},
"16": {
    "region": "\u0422\u0435\u0440\u043d\u043e\u043f\u0456\u043b\u044c\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 5.9015046296,
    "sirens_count": 137,
    "region_name": "\u0422\u0435\u0440\u043d\u043e\u043f\u0456\u043b\u044c\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "5 days 21:38:10",
    "sirens_dur_days_in_ua": "5 \u0434. 21 \u0433\u043e\u0434. 38 \u0445\u0432.",
    "sirens_duration_sec": 509890.0
},
"17": {
    "region": "\u0425\u043c\u0435\u043b\u044c\u043d\u0438\u0446\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 5.8516435185,
    "sirens_count": 134,
    "region_name": "\u0425\u043c\u0435\u043b\u044c\u043d\u0438\u0446\u044c\u043a\u0430",
    "sirens_dur_days": "5 days 20:26:22",
    "sirens_dur_days_in_ua": "5 \u0434. 20 \u0433\u043e\u0434. 26 \u0445\u0432.",
    "sirens_duration_sec": 505582.0
},
"18": {
    "region": "\u0412\u043e\u043b\u0438\u043d\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 5.7078125,
    "sirens_count": 163,
    "region_name": "\u0412\u043e\u043b\u0438\u043d\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "5 days 16:59:15",
    "sirens_dur_days_in_ua": "5 \u0434. 16 \u0433\u043e\u0434. 59 \u0445\u0432.",
    "sirens_duration_sec": 493155.0
},
"19": {
    "region": "\u0420\u0456\u0432\u043d\u0435\u043d\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 5.3617361111,
    "sirens_count": 149,
    "region_name": "\u0420\u0456\u0432\u043d\u0435\u043d\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "5 days 08:40:54",
    "sirens_dur_days_in_ua": "5 \u0434. 08 \u0433\u043e\u0434. 40 \u0445\u0432.",
    "sirens_duration_sec": 463254.0
},
"20": {
    "region": "\u041b\u044c\u0432\u0456\u0432\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 5.125625,
    "sirens_count": 137,
    "region_name": "\u041b\u044c\u0432\u0456\u0432\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "5 days 03:00:54",
    "sirens_dur_days_in_ua": "5 \u0434. 03 \u0433\u043e\u0434. 00 \u0445\u0432.",
    "sirens_duration_sec": 442854.0
},
"21": {
    "region": "\u0406\u0432\u0430\u043d\u043e-\u0424\u0440\u0430\u043d\u043a\u0456\u0432\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 4.7872800926,
    "sirens_count": 112,
    "region_name": "\u0406\u0432\u0430\u043d\u043e-\u0424\u0440\u0430\u043d\u043a\u0456\u0432\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "4 days 18:53:41",
    "sirens_dur_days_in_ua": "4 \u0434. 18 \u0433\u043e\u0434. 53 \u0445\u0432.",
    "sirens_duration_sec": 413621.0
},
"22": {
    "region": "\u0427\u0435\u0440\u043d\u0456\u0432\u0435\u0446\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 3.7838078704,
    "sirens_count": 78,
    "region_name": "\u0427\u0435\u0440\u043d\u0456\u0432\u0435\u0446\u044c\u043a\u0430",
    "sirens_dur_days": "3 days 18:48:41",
    "sirens_dur_days_in_ua": "3 \u0434. 18 \u0433\u043e\u0434. 48 \u0445\u0432.",
    "sirens_duration_sec": 326921.0
},
"23": {
    "region": "\u0417\u0430\u043a\u0430\u0440\u043f\u0430\u0442\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 3.2797800926,
    "sirens_count": 62,
    "region_name": "\u0417\u0430\u043a\u0430\u0440\u043f\u0430\u0442\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "3 days 06:42:53",
    "sirens_dur_days_in_ua": "3 \u0434. 06 \u0433\u043e\u0434. 42 \u0445\u0432.",
    "sirens_duration_sec": 283373.0
},
"24": {
    "region": "\u0425\u0435\u0440\u0441\u043e\u043d\u0441\u044c\u043a\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c",
    "sirens_duration": 0.2153587963,
    "sirens_count": 10,
    "region_name": "\u0425\u0435\u0440\u0441\u043e\u043d\u0441\u044c\u043a\u0430",
    "sirens_dur_days": "0 days 05:10:07",
    "sirens_dur_days_in_ua": "0 \u0434. 05 \u0433\u043e\u0434. 10 \u0445\u0432.",
    "sirens_duration_sec": 18607.0
}

}

出现双标是因为您将 y-scale 解析为独立的。如果你删除它,排序看起来会很乱,但那是因为你错过了气泡图的排序操作。添加它并采用稍微简单的方法将标签添加到气泡图,然后水平连接,你可以得到这个:

base = alt.Chart(df_viz2)

bar = base.mark_bar().encode(
    y = alt.Y(field='region_name', type='nominal',  title=None, 
              sort=alt.Sort(
                  field = 'sirens_duration', 
                  op = 'mean', 
                  order='descending'),
              axis = None
            )
    ,x = alt.X(field='sirens_duration', aggregate = 'mean', 
               axis = alt.Axis(
                  orient='top', 
                  grid=False, 
                  domain=False, 
                  labels=False,
                  ticks=False, 
                  title='Сумарна тривалість', 
                  titleAlign='right', 
                  titleX=100,
                  titleFontWeight='lighter'
                 ) 
    )
    ,color = alt.condition(
        alt.datum.region_name == 'Луганська',
        alt.value('#60bdb7'),
        alt.value('black')
    )
)

bar_text = bar.mark_text(align='left', baseline='middle', dx=4, fontSize = 14).encode(
    text = alt.Text(field = 'sirens_dur_days_in_ua', type = 'nominal'))


bubble = base.mark_circle(color='black', align='right').encode(
    y = alt.Y(field='region_name', type='nominal', sort=alt.Sort(field='sirens_duration',  op='mean', order='descending'), 
              title=None, 
              axis = alt.Axis(
                   offset=10
                  ,grid=False
                  ,domain=False
                  ,ticks=False
             ))
    ,size = alt.Size('sirens_count', legend=None)
  )

alt.hconcat(
    bubble,  bar + bar_text
).configure_view(
    strokeWidth = 0
).configure_axis(
    labelFontSize=16
    ,labelFont='Calibri'
).configure_axisX(
    titleFontSize=10
)