Altair / vega-lite 格式化条件文本值

Altair / vega-lite formatting a conditional text value

我成功地向 Altair 图表添加了自动工具提示,但我无法将文本格式化为货币。

这是我的代码:

contracts = {'date': ['2015-11-12','2020-11-11','2018-02-28','2021-02-27','2019-04-01','2021-03-31','2016-07-02','2019-11-01','2019-04-23','2019-10-14'],
        'type': ['Start date','End date','Start date','End date','Start date','End date','Start date','End date','Start date','End date',],
        'value': [2200000,2200000,250000,250000,127000,127000,35000,35000,148723,148723],
        'supplier': ['Capita','Capita','Deloitte','Deloitte','KPMG','KPMG','Herbert Smith','Herbert Smith','Spend Network','Spend Network'],
        'buyer': ['DWP','DWP','MOD','MOD','HMRC','HMRC','MOJ','MOJ','DFID','DFID']
        }

df = pd.DataFrame(contracts, columns=['date','type','value','supplier','buyer'])

# Create a selection that chooses the nearest point & selects based on x-value
nearest = alt.selection(type='single', nearest=True, on='mouseover',
                        fields=['date'], empty='none')

chart = alt.Chart(df, title="Pipeline").mark_point().encode(
    alt.X(
        'date:T',
        scale=alt.Scale(zero=False),
        axis=alt.Axis(grid=False)
    ),
    alt.Y(
        'supplier:N',
        title="",
        sort=alt.EncodingSortField(field='yield', op='sum', order='descending'),
        scale=alt.Scale(rangeStep=20),
        axis=alt.Axis(grid=True)
    ),
    alt.Size('value:Q',
        scale=alt.Scale(range=[40, 400]),
        legend=alt.Legend(title='Contract size')
    ),
    color=alt.Color('buyer:N', legend=alt.Legend(title="Buyer")),

)

line = alt.Chart(df).mark_line().encode(
    alt.X('date:T', 
            ## xAxis title must be "Source: https://openopps.com"
            axis=alt.Axis(title="Source: https://openopps.com") 
           ),
    alt.Y('supplier:N',
             ## This is our units section, only describe the units of measurement here.
             axis=alt.Axis(title="Units: contract duration, contract value")
           ),
    color=alt.Color('buyer:N'),
    )

# Transparent selectors across the chart. This is what tells us
# the x-value of the cursor
selectors = alt.Chart(df).mark_point().encode(
    x='date:T',
    opacity=alt.value(0),
    ).add_selection(
        nearest
    )

# Draw points on the line, and highlight based on selection
points = line.mark_point().encode(
    opacity=alt.condition(nearest, alt.value(1), alt.value(0))
)

# Draw text labels near the points, and highlight based on selection
text = line.mark_text(align='left', dx=5, dy=-5).encode(
        text=(
            alt.condition(nearest, 'value:Q', alt.value(' '))
    )
)

# Draw a rule at the location of the selection
rules = alt.Chart(df).mark_rule(color='gray').encode(
    x='date:T',
).transform_filter(
    nearest
)

# Put the five layers into a chart and bind the data
alt.layer(
    chart, line, selectors, points, rules, text
)

这给了我这个输出

您可以从突出显示的行中看出工具提示 (148723) 未格式化(例如,货币没有 $)。

我试过几件事,但都没有成功...

这种方法只会破坏整个图表格式,线条和图例以及 x 轴搞砸了。

# Draw text labels near the points, and highlight based on selection
text = line.mark_text(align='left', dx=5, dy=-5).encode(
        text=(
            alt.condition(nearest, 'value:Q', alt.value(' '), format='$.,3s')
    )
)

而且这种方法在验证时失败了。

# Draw text labels near the points, and highlight based on selection
text = line.mark_text(align='left', dx=5, dy=-5).encode(
        text=(
            alt.Text('value:Q', format='$.,3s'),
            alt.condition(nearest, 'value:Q', alt.value(' '))
    )
)

错误信息:

SchemaValidationError: Invalid specification

        altair.vegalite.v3.api.Chart, validating 'required'

        'data' is a required property

我很惊讶第一种方法不起作用,因为 alt.conditional 允许 **kwargs,但我想我误解了我可以传递给条件的内容。

您的格式字符串 "$.,3s" 无效。 Altair 使用来自 d3 format 的格式字符串,例如"$.2f"。您可以这样指定它:

# ...
    text=alt.condition(nearest, 'value:Q', alt.value(' '), format='$.2f')
# ...