如何在 Altair 的标准化条形图中放置分数标签?
How to put fraction labels in normalized bar chart in Altair?
import altair as alt
from vega_datasets import data
# get iris dataset and take 120 observations from it
source = data.iris()[10:130]
# add one more feature to dataset
colors = ['red', 'orange', 'blue', 'red'] * 30
source['colors'] = colors
chart = alt.Chart(source).mark_bar().encode(
alt.Y('species:N', sort='x'),
alt.X('count():Q', stack='zero'),
color=alt.Color('colors', sort=colors),
order="colors",
)
text = alt.Chart(source).mark_text(dx=-7, dy=3, color='white')\
.encode(
alt.Y("species:N", sort='x'),
alt.X('count():Q', stack="zero"),
order="colors",
text=alt.Text('count():Q')
)
chart + text
现在我想规范化此图表,标签应代表整体的一部分。
import altair as alt
from vega_datasets import data
source = data.iris()[10:130]
colors = ['red', 'orange', 'blue', 'red'] * 30
source['colors'] = colors
chart = alt.Chart(source).mark_bar().encode(
alt.Y('species:N', sort='x'),
alt.X('count():Q', stack='normalize'),
color=alt.Color('colors', sort=colors),
order="colors",
)
text = alt.Chart(source).mark_text(dx=-7, dy=3, color='white')\
.encode(
alt.Y("species:N", sort='x'),
alt.X('count():Q', stack="normalize"),
order="colors",
text=alt.Text('count():Q')
)
chart + text
因此,在此示例中,我希望看到 0.27、0.23、0.5(逗号后四舍五入为 2 位数)而不是第一个柱的 8、7、15。我怎样才能做到这一点?
更新
这就是我取得进步的方式:
import altair as alt
from vega_datasets import data
source = data.iris()[10:130]
colors = ['red', 'orange', 'blue', 'red'] * 30
sort_order=['blue', 'orange', 'red']
source['colors'] = colors
chart = alt.Chart(source).mark_bar().encode(
alt.Y('species:N', sort='x'),
alt.X('count():Q', stack='normalize'),
color=alt.Color('colors', sort=sort_order),
order = 'colors'
)
text = alt.Chart(source).transform_aggregate(count='count()', groupby=['species', 'colors'])\
.transform_joinaggregate(total='sum(count)', groupby=["species"])\
.transform_calculate(frac=alt.datum.count / alt.datum.total)\
.mark_text(align='right', dx=-7, dy=3, color='white')\
.encode(
alt.Y("species:N", sort='x'),
alt.X('count():Q', stack="normalize"),
text=alt.Text('frac:Q', format='.0%'),
order = 'colors'
)
chart + text
但是标签没有正确对齐(我需要它们恰好位于每种颜色的末尾,就像前两张图片中那样)。有什么解决办法吗?
您可以使用一系列joinaggregate and calculate transforms to compute the values you wish to display. You can use the format
text property to adjust the format using a d3-format字符串,以及align
标记属性来调整对齐方式。例如:
import altair as alt
from vega_datasets import data
source = data.iris()[10:130]
colors = ['red', 'orange', 'blue', 'red'] * 30
source['colors'] = colors
sort_order=['blue', 'orange', 'red']
chart = alt.Chart(source).mark_bar().encode(
alt.Y('species:N', sort='x'),
alt.X('count():Q', stack='normalize'),
color=alt.Color('colors', sort=sort_order),
order="colors",
)
text = chart.transform_joinaggregate(
count='count()',
groupby=['species', 'colors']
).transform_joinaggregate(
total='count()',
groupby=['species']
).transform_calculate(
fraction='datum.count / datum.total'
).mark_text(
dx=-7, dy=3, align='right'
).encode(
color=alt.ColorValue('white'),
text=alt.Text('fraction:Q', format='.2')
)
chart + text
(注意:我还通过共享两个图表之间的数据和编码使脚本更加简洁)
import altair as alt
from vega_datasets import data
# get iris dataset and take 120 observations from it
source = data.iris()[10:130]
# add one more feature to dataset
colors = ['red', 'orange', 'blue', 'red'] * 30
source['colors'] = colors
chart = alt.Chart(source).mark_bar().encode(
alt.Y('species:N', sort='x'),
alt.X('count():Q', stack='zero'),
color=alt.Color('colors', sort=colors),
order="colors",
)
text = alt.Chart(source).mark_text(dx=-7, dy=3, color='white')\
.encode(
alt.Y("species:N", sort='x'),
alt.X('count():Q', stack="zero"),
order="colors",
text=alt.Text('count():Q')
)
chart + text
现在我想规范化此图表,标签应代表整体的一部分。
import altair as alt
from vega_datasets import data
source = data.iris()[10:130]
colors = ['red', 'orange', 'blue', 'red'] * 30
source['colors'] = colors
chart = alt.Chart(source).mark_bar().encode(
alt.Y('species:N', sort='x'),
alt.X('count():Q', stack='normalize'),
color=alt.Color('colors', sort=colors),
order="colors",
)
text = alt.Chart(source).mark_text(dx=-7, dy=3, color='white')\
.encode(
alt.Y("species:N", sort='x'),
alt.X('count():Q', stack="normalize"),
order="colors",
text=alt.Text('count():Q')
)
chart + text
因此,在此示例中,我希望看到 0.27、0.23、0.5(逗号后四舍五入为 2 位数)而不是第一个柱的 8、7、15。我怎样才能做到这一点?
更新 这就是我取得进步的方式:
import altair as alt
from vega_datasets import data
source = data.iris()[10:130]
colors = ['red', 'orange', 'blue', 'red'] * 30
sort_order=['blue', 'orange', 'red']
source['colors'] = colors
chart = alt.Chart(source).mark_bar().encode(
alt.Y('species:N', sort='x'),
alt.X('count():Q', stack='normalize'),
color=alt.Color('colors', sort=sort_order),
order = 'colors'
)
text = alt.Chart(source).transform_aggregate(count='count()', groupby=['species', 'colors'])\
.transform_joinaggregate(total='sum(count)', groupby=["species"])\
.transform_calculate(frac=alt.datum.count / alt.datum.total)\
.mark_text(align='right', dx=-7, dy=3, color='white')\
.encode(
alt.Y("species:N", sort='x'),
alt.X('count():Q', stack="normalize"),
text=alt.Text('frac:Q', format='.0%'),
order = 'colors'
)
chart + text
但是标签没有正确对齐(我需要它们恰好位于每种颜色的末尾,就像前两张图片中那样)。有什么解决办法吗?
您可以使用一系列joinaggregate and calculate transforms to compute the values you wish to display. You can use the format
text property to adjust the format using a d3-format字符串,以及align
标记属性来调整对齐方式。例如:
import altair as alt
from vega_datasets import data
source = data.iris()[10:130]
colors = ['red', 'orange', 'blue', 'red'] * 30
source['colors'] = colors
sort_order=['blue', 'orange', 'red']
chart = alt.Chart(source).mark_bar().encode(
alt.Y('species:N', sort='x'),
alt.X('count():Q', stack='normalize'),
color=alt.Color('colors', sort=sort_order),
order="colors",
)
text = chart.transform_joinaggregate(
count='count()',
groupby=['species', 'colors']
).transform_joinaggregate(
total='count()',
groupby=['species']
).transform_calculate(
fraction='datum.count / datum.total'
).mark_text(
dx=-7, dy=3, align='right'
).encode(
color=alt.ColorValue('white'),
text=alt.Text('fraction:Q', format='.2')
)
chart + text
(注意:我还通过共享两个图表之间的数据和编码使脚本更加简洁)