Generate two legends via Altair - python

I would like to have two legends via Altair just like the picture below.
I have created the legend of "Count of actors", but I don't know how to generate the other one. My code is below:
plot = base.mark_circle(
opacity=0.8,
stroke='black',
strokeWidth=1
).encode(
alt.X('TYPE:O'),
alt.Y('index:N',
sort= movies_order
),
alt.Size('count(index):Q',
scale=alt.Scale(range=[0,4500]),
legend=alt.Legend(title='Count of actors', symbolFillColor='white')),
alt.Color('GENDER', legend=None)
#complete this
).properties(
width=350,
height=880
And the chart I created is like this:

This is the default behavior in Altair, but you have disabled the color legend. Change alt.Color('GENDER', legend=None) to alt.Color('GENDER').
Here is a modifed example for the Altair gallery with two legends:
import altair as alt
from vega_datasets import data
source = data.cars()
alt.Chart(source).mark_circle().encode(
x='Horsepower',
y='Miles_per_Gallon',
color='Origin',
size='Cylinders')

Related

Align rotated labels of Altair boxplot

I'm plotting a boxplot graph using Altair to divide the data into groups (similar to what was done here: Altair boxplot with nested grouping by two categorical variables) . The code I have is below:
import seaborn as sns
import altair as alt
tips = sns.load_dataset("tips")
tips = tips.replace('Sun', 'Sunday morning')
chart = alt.Chart(tips).mark_boxplot(ticks=True).encode(
x=alt.X("smoker:O", title=None, axis=alt.Axis(labels=False, ticks=False), scale=alt.Scale(padding=1)),
y=alt.Y("total_bill:Q"),
color="smoker:N",
column=alt.Column('day:N', sort=['Thur','Fri','Sat','Sunday morning'],header=alt.Header(labelPadding=-530,labelAngle=-90))
).properties(
width=80,
height = 350
).configure_view(
stroke=None
)
However, I can not manage to properly position the column labels after rotating them 90 degrees. In the image below, you can see the graph I'm getting in 'a', and the graph I would like to get in 'b'.
I looked for configurations on https://altair-viz.github.io/user_guide/configuration.html, but could not find a solution. Does anyone have an idea? (I'm using Altair 4.2.2 - the latest version).
I have tried various parameters, referring to this answer. I got the intended result by setting the label orient to bottom and modifying the padding. I don't have as much experience with Altair as you describe.
import seaborn as sns
import altair as alt
tips = sns.load_dataset("tips")
tips = tips.replace('Sun', 'Sunday morning')
chart = alt.Chart(tips).mark_boxplot(ticks=True).encode(
x=alt.X("smoker:O", title=None, axis=alt.Axis(labels=False, ticks=False), scale=alt.Scale(padding=1)),
y=alt.Y("total_bill:Q"),
color="smoker:N",
column=alt.Column('day:N',
sort=['Thur','Fri','Sat','Sunday morning'],
header=alt.Header(
labelPadding=360,
labelAngle=-90,
orient='bottom',
labelOrient='bottom',
labelAlign='right'
))
).properties(
width=80,
height = 350
).configure_view(
stroke=None
)
chart

Setting Colors in Altair Layered Chart

Similar to Setting colors in Altair charts I am using a layered chart and I like to set excplicit colors. Somehow, when I use the solution from the answer, my colors are always changing to some arbitrary colors. I wonder, if anyone knows, why this happens and how to force altair to use the colors given in the colors array.
Here a test example:
import altair as alt
from vega_datasets import data
source = data.movies()
colors = ['#170c3b', '#fa8d0b']
plot = alt.Chart(source).mark_line().encode(
x=alt.X("IMDB_Rating", bin=True),
y=alt.Y(
alt.repeat("layer"), aggregate="mean", title="Mean of US and Worldwide Gross"
),
color=alt.datum(alt.repeat("layer")),
).repeat(
layer=["US_Gross", "Worldwide_Gross"]
).configure_range(
category=alt.RangeScheme(scheme=colors)
)
plot.show()
Here the colors from the array:
#170c3b
#fa8d0b
Here the plot with changed colors:
The category=alt.RangeScheme(scheme=colors) should be category=alt.RangeScheme(colors) instead.
import altair as alt
from vega_datasets import data
source = data.movies()
colors = ['#170c3b', '#fa8d0b']
plot = alt.Chart(source).mark_line().encode(
x=alt.X("IMDB_Rating", bin=True),
y=alt.Y(
alt.repeat("layer"), aggregate="mean", title="Mean of US and Worldwide Gross"
),
color=alt.datum(alt.repeat("layer")),
).repeat(
layer=["US_Gross", "Worldwide_Gross"]
).configure_range(
category=alt.RangeScheme(colors)
)
plot
yields:

Is there a way to format tooltip values in Altair boxplot

Is is possible to format the values within a tooltip for a boxplot? From this Vega documentation, it appears so, but I can't quite figure out how to do it with Altair for python
from vega_datasets import data
import altair as alt
source = data.population.url
alt.Chart(source).mark_boxplot().encode(
alt.X("age:O"),
alt.Y("people:Q"),
tooltip=[
alt.Tooltip("people:Q", format=",.2f"),
],
)
I believe you need to provide an aggregation for composite marks like mark_boxplot. This works:
from vega_datasets import data
import altair as alt
source = data.population.url
alt.Chart(source).mark_boxplot().encode(
alt.X("age:O"),
alt.Y("people:Q"),
tooltip=alt.Tooltip("mean(people):Q", format=",.2f"),)
Update: As it is currently impossible to add multiple aggregated tooltips to a boxplot, I combined my answer with How to change Altair boxplot infobox to display mean rather than median? to put a transparent box with a custom tooltip on top of the boxplot. I still kept the boxplot underneath in order to have the outliers and whiskers plotted as a Tukey boxplot instead of min-max. I also added a point for the mean, since this is what I wanted to see in the tooltip:
alt.Chart(source).mark_boxplot(median={'color': '#353535'}).encode(
alt.X("age:O"),
alt.Y("people:Q"),
tooltip=[
alt.Tooltip("people:Q", format=",.2f"),
],
) + alt.Chart(source).mark_circle(color='#353535', size=15).encode(
x='age:O',
y='mean(people):Q'
) + alt.Chart(source).transform_aggregate(
min="min(people)",
max="max(people)",
mean="mean(people)",
median="median(people)",
q1="q1(people)",
q3="q3(people)",
count="count()",
groupby=['age']
).mark_bar(opacity=0).encode(
x='age:O',
y='q1:Q',
y2='q3:Q',
tooltip=alt.Tooltip(['min:Q', 'q1:Q', 'mean:Q', 'median:Q', 'q3:Q', 'max:Q', 'count:Q'], format='.1f')
)
There is a way to add multiple columns to the tooltip. You can pass in multiple columns in square brackets as a list.
import altair as alt
from vega_datasets import data
stocks = data.stocks()
alt.Chart(stocks).mark_point().transform_window(
previous_price = 'lag(price)'
).transform_calculate(
pct_change = '(datum.price - datum.previous_price) / datum.previous_price'
).encode(
x='date',
y='price',
color='symbol',
tooltip=[ 'price', 'symbol', alt.Tooltip('pct_change:Q', format='.1%')]
)

Is there anyway to popping out of part of Map or change of color on selection in Altair

I am trying to plot the states of India in altair.I am able to plot and in the tooltip state names are appearing.I want the state to pop out or change in color on selection.Is there any way to do it.
I tried to use selection_interval.But not able to do it as i am newbie
'''python
import altair as alt
url = "https://raw.githubusercontent.com/deldersveld/topojson/master/countries/india/india-states.json"
source = alt.topo_feature(url, "IND_adm1")
alt.Chart(source).mark_geoshape().encode(
tooltip='properties.NAME_1:N',
color=alt.value('lightgray')
).properties(
width=800,
height=500
)
You can use a Single Selection with a conditional color to do something like this:
import altair as alt
url = "https://raw.githubusercontent.com/deldersveld/topojson/master/countries/india/india-states.json"
source = alt.topo_feature(url, "IND_adm1")
hover = alt.selection_single(on='mouseover', empty='none')
alt.Chart(source).mark_geoshape().encode(
tooltip='properties.NAME_1:N',
color=alt.condition(hover, alt.value('steelblue'), alt.value('lightgray'))
).properties(
width=800,
height=500
).add_selection(
hover
)

How to do annotations with Altair?

I am trying to write some text inside the figure to highlight something in my plot (equivalent to 'annotate' in matplotlib). Any idea? Thanks
You can get annotations into your Altair plots in two steps:
Use mark_text() to specify the annotation's position, fontsize etc.
Use transform_filter() from datum to select the points (data subset) that needs the annotation. Note the line from altair import datum.
Code:
import altair as alt
from vega_datasets import data
alt.renderers.enable('notebook')
from altair import datum #Needed for subsetting (transforming data)
iris = data.iris()
points = alt.Chart(iris).mark_point().encode(
x='petalLength',
y='petalWidth',
color='species')
annotation = alt.Chart(iris).mark_text(
align='left',
baseline='middle',
fontSize = 20,
dx = 7
).encode(
x='petalLength',
y='petalWidth',
text='petalLength'
).transform_filter(
(datum.petalLength >= 5.1) & (datum.petalWidth < 1.6)
)
points + annotation
which produces:
These are static annotations. You can also get interactive annotations by binding selections to the plots.

Categories

Resources