Reputation: 67
I have a heatmap plotted using Altair that includes a colorbar, but the missing data (blank/white) in the heatmap is not labeled on the colorbar. Is there a way to add a separate label to the legend (e.g. below the colorbar) to show how missing data is represented in the chart?
I've come up with a solution that includes a "ghost" layer on top of my chart -- a ruler chart with size = 0 (so that the line is invisible) that is colored by a column filled with string values of "No Data" (see code below). This forces a legend item, but I'm wondering if there's a better way. (See my full example at link here:heatmap plot)
import numpy as np
import altair as alt
import pandas as pd
# Example heatmap data
heatmap_df = pd.DataFrame([["NY",1999,1],["NY",2000,np.nan], ["MA",1999,np.nan], ["MA",2000,4]], columns = ["state","year","rate"])
# Example Legend dataframe
legend_no_data = pd.DataFrame([[1999, "No Data"]], columns = ["year", "text"])
# Example chart with "No Data" label
heatmap = alt.Chart(heatmap_df).mark_rect().encode(alt.X("year:O"), alt.Y("state:N"), alt.Color("rate:Q"))
# Chart for "No Data" legend item
vacc_legend_no_data = alt.Chart(legend_no_data).mark_line(
size=0
).encode(
x='year:O',
color = alt.Color("text:N", legend = alt.Legend(title = "", symbolType = "square")))
heatmap + vacc_legend_no_data
The "ghost layer" adds the empty square labeled "No Data" at the bottom of the colorbar, but I hope there is a better way to represent this!
Upvotes: 3
Views: 1088
Reputation: 86443
Unfortunately, I don't know an easy way to handle nulls within a quantitative scale. But you can handle them naturally within nominal scales; I would probably generate the Null dataset layer in the chart spec using a calculate transform, to avoid having to construct a second dataframe. It might look something like this:
heatmap = alt.Chart(heatmap_df).mark_rect().encode(
alt.X("year:O"),
alt.Y("state:N"),
alt.Color("rate:Q")
)
nulls = heatmap.transform_filter(
"!isValid(datum.rate)"
).mark_rect(opacity=0.5).encode(
alt.Color('rate:N', scale=alt.Scale(scheme='greys'))
)
heatmap + nulls
Upvotes: 7