[英]How to sort Y-axis labels different for each row in my plot?
I want each subplot to sort the labels based on the value defining the size of the bar. 我希望每个子图根据定义条形大小的值对标签进行排序。
See example image: 见示例图片:
data = {'label': ['A','A','B','B'], 'variable': ['x', 'y', 'x', 'y'], 'value':[2,4,3,1]}
df = pd.DataFrame.from_dict(data)
selector = alt.selection_single(empty='all', fields=['label'])
bar = alt.Chart(df,title='My Plot').mark_bar().encode(
alt.Y('label', sort=alt.EncodingSortField(field="value", op="mean", order='ascending'), axis=alt.Axis(title='Label')),
alt.X('value:Q', axis=alt.Axis(format='%', title='Value')),
alt.Row('variable', title='Variable'),
color=alt.condition(selector, alt.value('orange'), alt.value('lightgray')),
tooltip=[alt.Tooltip('label', title='Label'),
alt.Tooltip('value:Q', format='.2%', title='Value'),]
).add_selection(selector)
chart = (bar).properties(width=700, height=300)
display(chart)
In the example, the labels (A, B) are now sorted based on the mean of all values for those labels. 在示例中,标签(A,B)现在根据这些标签的所有值的平均值进行排序。 I want the order to be BA for label X and AB for label Y (so descending based on the value of the label showed in the row of the Altair plot).
我希望订单为标签X的BA和标签Y的AB(因此,根据Altair图的行中显示的标签值降序)。
I tried using facet but that did not resolve the issue. 我尝试使用facet但是没有解决问题。 I provide the code here because it can maybe inspire a solution :
我在这里提供代码,因为它可以激发解决方案:
import altair as alt
import pandas as pd
df = pd.DataFrame({'label': ['A','A','B','B'],
'variable': ['x', 'y', 'x', 'y'],
'value':[2,4,3,1]})
bar = alt.Chart(df,title='My Plot').mark_bar().encode(
alt.Y('label', axis=alt.Axis(title='Label'),
sort=alt.EncodingSortField(field="value", op="values", order='descending')),
alt.X('value:Q', axis=alt.Axis(format='d', title='Value')),
tooltip=[alt.Tooltip('label', title='Label'),
alt.Tooltip('value:Q', format='d', title='Value'),]
).facet(
row='variable:O'
)
bar
Still the row order is ['B', 'A'] for variable x and y. 对于变量x和y,行顺序仍为['B','A']。 I was hoping to have ['A', 'B] for the variable y bar chart.
我希望变量y条形图有['A','B]。
Further elaborating on the solution provided by jakevdp, i obtain this: 进一步详细阐述了jakevdp提供的解决方案,我得到了这个:
selector = alt.selection_single(empty='all', fields=['label'])
base = alt.Chart(df, title='My Plot').mark_bar().encode(
alt.Y('label', axis=alt.Axis(title='Label'), sort=alt.EncodingSortField(field="value", op="sum", order='descending')),
alt.X('value:Q', axis=alt.Axis(format='d', title='Value')),
color=alt.condition(selector, alt.value('orange'), alt.value('lightgray')),
tooltip=[alt.Tooltip('label', title='Label'),
alt.Tooltip('value:Q', format='d', title='Value'),]
).add_selection(selector)
bar = alt.vconcat(title='My Chart')
for v in df['variable'].unique():
bar &= base.transform_filter(f"datum.variable == '{v}'").properties(title=f"'{v}'")
bar
By design facet charts share their axes, so it means that when you sort the column you are sorting both axes by the entire dataset. 通过设计构面图共享它们的轴,这意味着当您对列进行排序时,您将按整个数据集对两个轴进行排序。
If you would like each chart to have its axis sorted individually, I believe the only way to do that is to manually filter the dataset and concatenate the charts. 如果您希望每个图表单独对其轴进行排序,我认为唯一的方法是手动过滤数据集并连接图表。 Here is one way you might do this:
这是你可以这样做的一种方式:
import altair as alt
import pandas as pd
df = pd.DataFrame({'label': ['A','A','B','B'],
'variable': ['x', 'y', 'x', 'y'],
'value':[2,4,3,1]})
base = alt.Chart(df).mark_bar().encode(
alt.Y('label', axis=alt.Axis(title='Label'),
sort=alt.EncodingSortField(field="value", op="sum", order='descending')),
alt.X('value:Q', axis=alt.Axis(format='d', title='Value')),
tooltip=[alt.Tooltip('label', title='Label'),
alt.Tooltip('value:Q', format='d', title='Value'),],
)
alt.vconcat(
base.transform_filter("datum.variable == 'x'").properties(title='x'),
base.transform_filter("datum.variable == 'y'").properties(title='y'),
title='My Chart'
)
Facet has shared scales by default, but you can override scale resolution with the resolve property: 默认情况下,Facet具有共享比例,但您可以使用resolve属性覆盖比例分辨率:
import altair as alt
import pandas as pd
df = pd.DataFrame({'label': ['A','A','B','B'],
'variable': ['x', 'y', 'x', 'y'],
'value':[2,4,3,1]})
alt.Chart(df,title='My Plot').mark_bar().encode(
alt.Y('label', sort=alt.EncodingSortField(field="value", op="mean", order='descending'), axis=alt.Axis(title='Label')),
alt.X('value:Q', axis=alt.Axis(format='%', title='Value'))
).facet(
alt.Row('variable', title='Variable'),
resolve={"scale": {"y": "independent"}}
)
Note that you can no longer use the row encoding shorthand in Altair 2 since unit specifications with row/column in Altair 2 (and Vega-Lite 2) do not have the resolve
property. 请注意,您不能再在Altair 2中使用行编码速记,因为Altair 2(和Vega-Lite 2)中具有行/列的单元规范没有
resolve
属性。 We now added resolve
to Vega-Lite 3, thus I think you should be able to do the following once Altair 3 is out: 我们现在为Vega-Lite 3添加了
resolve
,因此我认为一旦Altair 3出局,您应该能够执行以下操作:
df = pd.DataFrame({'label': ['A','A','B','B'],
'variable': ['x', 'y', 'x', 'y'],
'value':[2,4,3,1]})
alt.Chart(df,title='My Plot', resolve={"scale": {"y": "independent"}}).mark_bar().encode(
alt.Y('label', sort=alt.EncodingSortField(field="value", op="mean", order='descending'), axis=alt.Axis(title='Label')),
alt.X('value:Q', axis=alt.Axis(format='%', title='Value')),
alt.Row('variable', title='Variable')
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.