簡體   English   中英

Altair 雙軸 y

[英]Dual axes for y with 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 ,同時能夠在我在繪圖上移動鼠標時同時顯示y1y2的值。 我在網上搜索,發現我可能需要使用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()

這在某種程度上有效,但我有以下問題:

  1. 由於僅在base選擇了x ,因此交互式繪圖僅顯示 x 軸上的點而不是線上的點;
  2. 僅顯示一行的 y 值(而不是兩者),如points()text指定的那樣;
  3. 如何為兩條線創建圖例?

我正在考慮將y1y2合並為一列。 這會讓做我想做的事情更容易嗎?

我相信resolve_scale是你所需要的。

將您的圖表放入 "()" 中,然后.resolve_scale(y='independent')文檔中的示例所示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM