altair 中的多项选择
Multiple selections in altair
我想要两个交互式图例,类似于中的第二个例子
this section
Altair 文档,但没有矩形图例。
一个图例应通过一个分类变量 ("First name") 控制颜色,而第二个图例应通过另一个分类变量 ("Last name") 控制标记。虽然我能够获得正确的美学效果(见下图),但第二个图例的交互性会导致意外行为。
我生成上图的代码如下:
import pandas as pd
import altair as alt
# Create dataframe
data = [[7, 10, 'Alex', 'Smith'],
[12, 20, 'Bob', 'Jones'],
[10, 30, 'Clive', 'Smith'],
[42, 40, 'Alex', 'Johnson']]
df = pd.DataFrame(data,columns=['Favorite number', 'Age', 'First name', 'Last name'])
# Create selections
selection_first_name = alt.selection_multi(fields=['First name'])
selection_last_name = alt.selection_multi(fields=['Last name'])
# Create first name conditions
color_first_name = alt.condition(selection_first_name,
alt.Color('First name:N', legend=None),
alt.value('lightgray'))
# Create last name conditions
shape_last_name = alt.condition(selection_last_name,
alt.Shape('Last name:N', legend=None),
alt.value('lightgray'))
# Create interactive scatter plot
scatter = alt.Chart(df).mark_point(size=100).encode(
x='Favorite number:Q',
y='Age:Q',
color=color_first_name,
shape=shape_last_name,
tooltip=['First name', 'Last name']
).add_selection(
selection_first_name
).add_selection(
selection_last_name
).add_selection(
alt.selection_interval(bind='scales')
)
# Create interactive model name legend
legend_first_name = alt.Chart(df).mark_point(size=100).encode(
y=alt.Y('First name:N', axis=alt.Axis(orient='right')),
color=color_first_name
).add_selection(
selection_first_name
)
# Create interactive model name legend
legend_last_name = alt.Chart(df).mark_point(size=100).encode(
y=alt.Y('Last name:N', axis=alt.Axis(orient='right')),
shape=shape_last_name
).add_selection(
selection_last_name
)
# Combine plotting elements
chart = scatter | legend_first_name | legend_last_name
生成的 HTML 图表在此处:
<!DOCTYPE html>
<html>
<head>
<style>
.vega-actions a {
margin-right: 12px;
color: #757575;
font-weight: normal;
font-size: 13px;
}
.error {
color: red;
}
</style>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm//vega@5"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm//vega-lite@3.4.0"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm//vega-embed@4"></script>
</head>
<body>
<div id="vis"></div>
<script>
(function(vegaEmbed) {
var spec = {"config": {"view": {"width": 400, "height": 300}, "mark": {"tooltip": null}}, "hconcat": [{"mark": {"type": "point", "size": 100}, "encoding": {"color": {"condition": {"type": "nominal", "field": "First name", "legend": null, "selection": "selector001"}, "value": "lightgray"}, "shape": {"condition": {"type": "nominal", "field": "Last name", "legend": null, "selection": "selector002"}, "value": "lightgray"}, "tooltip": [{"type": "nominal", "field": "First name"}, {"type": "nominal", "field": "Last name"}], "x": {"type": "quantitative", "field": "Favorite number"}, "y": {"type": "quantitative", "field": "Age"}}, "selection": {"selector001": {"type": "multi", "fields": ["First name"]}, "selector002": {"type": "multi", "fields": ["Last name"]}, "selector003": {"type": "interval", "bind": "scales"}}}, {"mark": {"type": "point", "size": 100}, "encoding": {"color": {"condition": {"type": "nominal", "field": "First name", "legend": null, "selection": "selector001"}, "value": "lightgray"}, "y": {"type": "nominal", "axis": {"orient": "right"}, "field": "First name"}}, "selection": {"selector001": {"type": "multi", "fields": ["First name"]}}}, {"mark": {"type": "point", "size": 100}, "encoding": {"shape": {"condition": {"type": "nominal", "field": "Last name", "legend": null, "selection": "selector002"}, "value": "lightgray"}, "y": {"type": "nominal", "axis": {"orient": "right"}, "field": "Last name"}}, "selection": {"selector002": {"type": "multi", "fields": ["Last name"]}}}], "data": {"name": "data-ec767a72044047bc9825da631c9465fc"}, "$schema": "https://vega.github.io/schema/vega-lite/v3.4.0.json", "datasets": {"data-ec767a72044047bc9825da631c9465fc": [{"Favorite number": 7, "Age": 10, "First name": "Alex", "Last name": "Smith"}, {"Favorite number": 12, "Age": 20, "First name": "Bob", "Last name": "Jones"}, {"Favorite number": 10, "Age": 30, "First name": "Clive", "Last name": "Smith"}, {"Favorite number": 42, "Age": 40, "First name": "Alex", "Last name": "Johnson"}]}};
var embedOpt = {"mode": "vega-lite"};
function showError(el, error){
el.innerHTML = ('<div class="error" style="color:red;">'
+ '<p>JavaScript Error: ' + error.message + '</p>'
+ "<p>This usually means there's a typo in your chart specification. "
+ "See the javascript console for the full traceback.</p>"
+ '</div>');
throw error;
}
const el = document.getElementById('vis');
vegaEmbed("#vis", spec, embedOpt)
.catch(error => showError(el, error));
})(vegaEmbed);
</script>
</body>
</html>
您的形状编码条件如下所示:
shape_last_name = alt.condition(selection_last_name,
alt.Shape('Last name:N', legend=None),
alt.value('lightgray'))
它指定当一个点未被选中时,它应该具有名为 lightgray
的形状。 lightgray
不是有效的形状,因此未绘制任何点。
如果你想根据形状选择改变颜色,你应该把条件放在颜色编码中。如果要根据形状图例选择更改形状,则应在条件内使用有效的形状值。
我怀疑你想要的是这样的:
import pandas as pd
import altair as alt
# Create dataframe
data = [[7, 10, 'Alex', 'Smith'],
[12, 20, 'Bob', 'Jones'],
[10, 30, 'Clive', 'Smith'],
[42, 40, 'Alex', 'Johnson']]
df = pd.DataFrame(data,columns=['Favorite number', 'Age', 'First name', 'Last name'])
# Create selections
selection_first_name = alt.selection_multi(fields=['First name'], empty='none')
selection_last_name = alt.selection_multi(fields=['Last name'], empty='none')
# Create interactive scatter plot
scatter = alt.Chart(df).mark_point(size=100).encode(
x='Favorite number:Q',
y='Age:Q',
color=alt.condition(selection_first_name & selection_last_name,
alt.Color('First name:N', legend=None),
alt.value('lightgray') ),
shape=alt.Shape('Last name:N', legend=None),
tooltip=['First name', 'Last name']
).add_selection(
alt.selection_interval(bind='scales')
)
# Create interactive model name legend
legend_first_name = alt.Chart(df).mark_point(size=100).encode(
y=alt.Y('First name:N', axis=alt.Axis(orient='right')),
color=alt.condition(selection_first_name,
alt.Color('First name:N', legend=None),
alt.value('lightgray') ),
).add_selection(
selection_first_name
)
# Create interactive model name legend
legend_last_name = alt.Chart(df).mark_point(size=100).encode(
y=alt.Y('Last name:N', axis=alt.Axis(orient='right')),
shape=alt.Shape('Last name:N', legend=None),
color=alt.condition(selection_last_name,
alt.value('black'),
alt.value('lightgray') ),
).add_selection(
selection_last_name
)
# Combine plotting elements
chart = scatter | legend_first_name | legend_last_name
我想要两个交互式图例,类似于中的第二个例子 this section Altair 文档,但没有矩形图例。 一个图例应通过一个分类变量 ("First name") 控制颜色,而第二个图例应通过另一个分类变量 ("Last name") 控制标记。虽然我能够获得正确的美学效果(见下图),但第二个图例的交互性会导致意外行为。
我生成上图的代码如下:
import pandas as pd
import altair as alt
# Create dataframe
data = [[7, 10, 'Alex', 'Smith'],
[12, 20, 'Bob', 'Jones'],
[10, 30, 'Clive', 'Smith'],
[42, 40, 'Alex', 'Johnson']]
df = pd.DataFrame(data,columns=['Favorite number', 'Age', 'First name', 'Last name'])
# Create selections
selection_first_name = alt.selection_multi(fields=['First name'])
selection_last_name = alt.selection_multi(fields=['Last name'])
# Create first name conditions
color_first_name = alt.condition(selection_first_name,
alt.Color('First name:N', legend=None),
alt.value('lightgray'))
# Create last name conditions
shape_last_name = alt.condition(selection_last_name,
alt.Shape('Last name:N', legend=None),
alt.value('lightgray'))
# Create interactive scatter plot
scatter = alt.Chart(df).mark_point(size=100).encode(
x='Favorite number:Q',
y='Age:Q',
color=color_first_name,
shape=shape_last_name,
tooltip=['First name', 'Last name']
).add_selection(
selection_first_name
).add_selection(
selection_last_name
).add_selection(
alt.selection_interval(bind='scales')
)
# Create interactive model name legend
legend_first_name = alt.Chart(df).mark_point(size=100).encode(
y=alt.Y('First name:N', axis=alt.Axis(orient='right')),
color=color_first_name
).add_selection(
selection_first_name
)
# Create interactive model name legend
legend_last_name = alt.Chart(df).mark_point(size=100).encode(
y=alt.Y('Last name:N', axis=alt.Axis(orient='right')),
shape=shape_last_name
).add_selection(
selection_last_name
)
# Combine plotting elements
chart = scatter | legend_first_name | legend_last_name
生成的 HTML 图表在此处:
<!DOCTYPE html>
<html>
<head>
<style>
.vega-actions a {
margin-right: 12px;
color: #757575;
font-weight: normal;
font-size: 13px;
}
.error {
color: red;
}
</style>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm//vega@5"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm//vega-lite@3.4.0"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm//vega-embed@4"></script>
</head>
<body>
<div id="vis"></div>
<script>
(function(vegaEmbed) {
var spec = {"config": {"view": {"width": 400, "height": 300}, "mark": {"tooltip": null}}, "hconcat": [{"mark": {"type": "point", "size": 100}, "encoding": {"color": {"condition": {"type": "nominal", "field": "First name", "legend": null, "selection": "selector001"}, "value": "lightgray"}, "shape": {"condition": {"type": "nominal", "field": "Last name", "legend": null, "selection": "selector002"}, "value": "lightgray"}, "tooltip": [{"type": "nominal", "field": "First name"}, {"type": "nominal", "field": "Last name"}], "x": {"type": "quantitative", "field": "Favorite number"}, "y": {"type": "quantitative", "field": "Age"}}, "selection": {"selector001": {"type": "multi", "fields": ["First name"]}, "selector002": {"type": "multi", "fields": ["Last name"]}, "selector003": {"type": "interval", "bind": "scales"}}}, {"mark": {"type": "point", "size": 100}, "encoding": {"color": {"condition": {"type": "nominal", "field": "First name", "legend": null, "selection": "selector001"}, "value": "lightgray"}, "y": {"type": "nominal", "axis": {"orient": "right"}, "field": "First name"}}, "selection": {"selector001": {"type": "multi", "fields": ["First name"]}}}, {"mark": {"type": "point", "size": 100}, "encoding": {"shape": {"condition": {"type": "nominal", "field": "Last name", "legend": null, "selection": "selector002"}, "value": "lightgray"}, "y": {"type": "nominal", "axis": {"orient": "right"}, "field": "Last name"}}, "selection": {"selector002": {"type": "multi", "fields": ["Last name"]}}}], "data": {"name": "data-ec767a72044047bc9825da631c9465fc"}, "$schema": "https://vega.github.io/schema/vega-lite/v3.4.0.json", "datasets": {"data-ec767a72044047bc9825da631c9465fc": [{"Favorite number": 7, "Age": 10, "First name": "Alex", "Last name": "Smith"}, {"Favorite number": 12, "Age": 20, "First name": "Bob", "Last name": "Jones"}, {"Favorite number": 10, "Age": 30, "First name": "Clive", "Last name": "Smith"}, {"Favorite number": 42, "Age": 40, "First name": "Alex", "Last name": "Johnson"}]}};
var embedOpt = {"mode": "vega-lite"};
function showError(el, error){
el.innerHTML = ('<div class="error" style="color:red;">'
+ '<p>JavaScript Error: ' + error.message + '</p>'
+ "<p>This usually means there's a typo in your chart specification. "
+ "See the javascript console for the full traceback.</p>"
+ '</div>');
throw error;
}
const el = document.getElementById('vis');
vegaEmbed("#vis", spec, embedOpt)
.catch(error => showError(el, error));
})(vegaEmbed);
</script>
</body>
</html>
您的形状编码条件如下所示:
shape_last_name = alt.condition(selection_last_name,
alt.Shape('Last name:N', legend=None),
alt.value('lightgray'))
它指定当一个点未被选中时,它应该具有名为 lightgray
的形状。 lightgray
不是有效的形状,因此未绘制任何点。
如果你想根据形状选择改变颜色,你应该把条件放在颜色编码中。如果要根据形状图例选择更改形状,则应在条件内使用有效的形状值。
我怀疑你想要的是这样的:
import pandas as pd
import altair as alt
# Create dataframe
data = [[7, 10, 'Alex', 'Smith'],
[12, 20, 'Bob', 'Jones'],
[10, 30, 'Clive', 'Smith'],
[42, 40, 'Alex', 'Johnson']]
df = pd.DataFrame(data,columns=['Favorite number', 'Age', 'First name', 'Last name'])
# Create selections
selection_first_name = alt.selection_multi(fields=['First name'], empty='none')
selection_last_name = alt.selection_multi(fields=['Last name'], empty='none')
# Create interactive scatter plot
scatter = alt.Chart(df).mark_point(size=100).encode(
x='Favorite number:Q',
y='Age:Q',
color=alt.condition(selection_first_name & selection_last_name,
alt.Color('First name:N', legend=None),
alt.value('lightgray') ),
shape=alt.Shape('Last name:N', legend=None),
tooltip=['First name', 'Last name']
).add_selection(
alt.selection_interval(bind='scales')
)
# Create interactive model name legend
legend_first_name = alt.Chart(df).mark_point(size=100).encode(
y=alt.Y('First name:N', axis=alt.Axis(orient='right')),
color=alt.condition(selection_first_name,
alt.Color('First name:N', legend=None),
alt.value('lightgray') ),
).add_selection(
selection_first_name
)
# Create interactive model name legend
legend_last_name = alt.Chart(df).mark_point(size=100).encode(
y=alt.Y('Last name:N', axis=alt.Axis(orient='right')),
shape=alt.Shape('Last name:N', legend=None),
color=alt.condition(selection_last_name,
alt.value('black'),
alt.value('lightgray') ),
).add_selection(
selection_last_name
)
# Combine plotting elements
chart = scatter | legend_first_name | legend_last_name