使用Altair的y的双轴

时间:2019-06-08 03:56:11

标签: python plot axes altair

我正在尝试创建一个具有双轴的交互式图。例如,我想对y1y2使用两个轴,因为它们的大小不同:

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')

以上代码分别适用于y1y2。现在,我想在同一绘图中在左侧y轴上绘制y1和在右侧y轴上绘制y2,同时能够显示y1和{{1 }}同时在图上移动鼠标。我在网上搜索后发现可能需要使用y2,但我不知道该如何使用。

编辑: 我尝试了以下代码:

resolve_scale()

这在一定程度上可行,但是我有以下问题:

  1. 由于在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,因此交互式绘图仅在x轴上显示点,而不是在直线上;
  2. 仅显示basepoints()中指定的一行(两个除外)的y值;
  3. 如何为这两行创建图例?

我正在考虑将texty1融合到一栏中。这样会使做我想做的事情变得容易吗?

1 个答案:

答案 0 :(得分:3)

我相信resolve_scale是您所需要的。

将图表放入“()”,然后依次放入.resolve_scale(y='independent')