我正在尝试创建一个具有双轴的交互式图。例如,我想对y1
和y2
使用两个轴,因为它们的幅度不同:
import altair as alt
import pandas as pd
import numpy as np
np.random.seed(42)
source = pd.DataFrame(np.cumsum(np.random.randn(100, 1), 0).round(2),
columns=['A'], index=pd.RangeIndex(100, name='x'))
source = source.reset_index().melt('x', var_name='category', value_name='y1')
source['Type'] = 'First'
source_1 = source.copy()
source_1['y1'] = source_1['y1'] + 5
source_1['Type'] = 'Second'
source_2 = source.copy()
source_2['y1'] = source_2['y1'] - 5
source_2['Type'] = 'Third'
source = pd.concat([source, source_1, source_2])
source['y2'] = source['y1']/10
def singleY_chart(y):
input_dropdown = alt.binding_select(options=['First', 'Second', 'Third'])
selection = alt.selection_single(name='Select', fields=['Type'],
bind=input_dropdown)
# Create a selection that chooses the nearest point & selects based on x-value
nearest = alt.selection(type='single', nearest=True, on='mouseover',
fields=['x'], empty='none')
# The basic line
base = alt.Chart(source).encode(
alt.X('x:Q'),
alt.Y(y, type='quantitative')
).transform_filter(selection)
# add drop-down menu
line = base.mark_line().add_selection(selection)
# Transparent selectors across the chart. This is what tells us
# the x-value of the cursor
selectors = alt.Chart(source).mark_point().encode(
x='x:Q',
opacity=alt.value(0),
).add_selection(
nearest
)
# Draw points on the line, and highlight based on selection
points = base.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 = base.mark_text(align='left', dx=5, dy=-5).encode(
text=alt.condition(nearest, alt.Y(y, type='quantitative'), alt.value(' '))
)
# Draw a rule at the location of the selection
rules = alt.Chart(source).mark_rule(color='gray').encode(
x='x:Q',
).transform_filter(
nearest
)
# Put the five layers into a chart and bind the data
chart = alt.layer(
line, selectors, points, rules, text
).properties(
width=500, height=300
).configure_axisX(
labelAngle=0
).configure_axis(
titleFontSize=12.5,
labelFontSize=12.5
).configure_legend(
titleFontSize=12.5,
labelFontSize=12.5
)
return chart
singleY_chart('y1')
# singleY_chart('y2')
以上代码分别适用于y1
或y2
。现在,我想在同一绘图中在左侧y轴上绘制y1
,在右侧y轴上绘制y2
,同时在移动时能够同时显示y1
和y2
的值我的鼠标在情节上。我在网上搜索后发现可能需要使用resolve_scale()
,但无法弄清楚该如何使用。
编辑:我尝试了以下代码:
import altair as alt
import pandas as pd
import numpy as np
np.random.seed(42)
source = pd.DataFrame(np.cumsum(np.random.randn(100, 1), 0).round(2),
columns=['A'], index=pd.RangeIndex(100, name='x'))
source = source.reset_index().melt('x', var_name='category', value_name='y1')
source['Type'] = 'First'
source_1 = source.copy()
source_1['y1'] = source_1['y1'] + 5
source_1['Type'] = 'Second'
source_2 = source.copy()
source_2['y1'] = source_2['y1'] - 5
source_2['Type'] = 'Third'
source = pd.concat([source, source_1, source_2])
source['y2'] = source['y1']/10 + np.random.randn(300, )/10
def singleY_chart():
input_dropdown = alt.binding_select(options=['First', 'Second', 'Third'])
selection = alt.selection_single(name='Select', fields=['Type'],
bind=input_dropdown)
# Create a selection that chooses the nearest point & selects based on x-value
nearest = alt.selection(type='single', nearest=True, on='mouseover',
fields=['x'], empty='none')
# The basic line
base = alt.Chart(source).encode(
alt.X('x:Q')
).transform_filter(selection)
# add drop-down menu
line_1 = base.mark_line().encode(alt.Y('y1'),
color=alt.value('red')).add_selection(selection)
line_2 = base.mark_line().encode(alt.Y('y2'),
color=alt.value('blue'))
# Transparent selectors across the chart. This is what tells us
# the x-value of the cursor
selectors = alt.Chart(source).mark_point().encode(
x='x:Q',
opacity=alt.value(0),
).add_selection(
nearest
)
# Draw points on the line, and highlight based on selection
points = base.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 = base.mark_text(align='left', dx=5, dy=-5).encode(
text=alt.condition(nearest, alt.Y('y2:Q'), alt.value(' '))
)
# Draw a rule at the location of the selection
rules = alt.Chart(source).mark_rule(color='gray').encode(
x='x:Q',
).transform_filter(
nearest
)
# Put the five layers into a chart and bind the data
chart = alt.layer(
line_1, line_2, selectors, points, rules, text
).resolve_scale(
y='independent'
).properties(
width=500, height=300
).configure_axisX(
labelAngle=0
).configure_axis(
titleFontSize=12.5,
labelFontSize=12.5
).configure_legend(
titleFontSize=12.5,
labelFontSize=12.5
)
return chart
singleY_chart()
这在某种程度上有效,但是我有以下问题:
x
中选择了base
,所以交互式绘图仅在x轴上显示点,而不是在直线上显示];points()
和text
中指定的一行的y值(而不是两者);我正在考虑将y1
和y2
融合为一列。这样会使我想要做的事情更容易吗?
我正在尝试创建一个具有双轴的交互式图。例如,我要对y1和y2使用两个轴,因为它们的大小不同:import altair as alt import pandas as pd import numpy as ...
我相信您需要的是resolve_scale。