Как построить многослойную диаграмму Альтаира с двойной осью?

Описание

Этот код показывает три диаграммы Альтаира:

  1. scatter
  2. rate
  3. line_plot

Цель

Цель состоит в том, чтобы объединить все диаграммы в многоуровневую диаграмму со следующими характеристиками:

  • показать ось Y для scatter и rate (т. е. диаграмма с двумя осями)
  • фасет от Series
  • показать line_plot.

Код

    import altair as alt
    from vega_datasets import data
    import pandas as pd
    
    source = data.anscombe().copy()
    source['line-label'] = 'x=y'
    source = pd.concat([source,source.groupby('Series').agg(x_diff=('X','diff'), y_diff=('Y','diff'))],axis=1)
    source['rate'] = source.y_diff/source.x_diff
    source['rate-label'] = 'rate of change'
    source['line-label'] = 'line y=x'
    
    source_linear = source.groupby(by=['Series']).agg(x_linear=('X','max'), y_linear=('X', 'max')).reset_index().sort_values(by=['Series'])
    
    source_origin = source_linear.copy()
    source_origin['y_linear'] = 0
    source_origin['x_linear'] = 0
    
    source_linear = pd.concat([source_origin,source_linear]).sort_values(by=['Series'])
    
    source = source.merge(source_linear,on='Series').drop_duplicates()
    
    scatter = alt.Chart(source).mark_circle(size=60, opacity=0.60).encode(
        x=alt.X('X', title='X'),
        y=alt.Y('Y', title='Y'),
        color='Series:N',
        tooltip=['X','Y','rate']
    )
    
    line_plot = alt.Chart(source).mark_line(color= 'black', strokeDash=[3,8]).encode(
        x=alt.X('x_linear', title = ''),
        y=alt.Y('y_linear', title = ''),
        shape = alt.Shape('line-label', title = 'Break Even'),
        color = alt.value('black')
    )
    
    rate =  alt.Chart(source).mark_line(strokeDash=[5,3]).encode(
        x=alt.X('X', title = 'X'),
        y=alt.Y('rate:Q'),
        color = alt.Color('rate-label',),
        tooltip=['rate','X','Y']
    )

Текущее решение

Проблема с текущим решением заключается в том, что ось y диаграммы rate не отображается как двойная ось. Какие-либо предложения?

    alt.layer(rate,scatter,line_plot).facet(
        'Series:N'
        , columns=2
    ).resolve_scale(
        x='independent',
        y='independent'
    ).display()

Проблемы с двойной осью


person blehman    schedule 30.10.2020    source источник
comment
К сожалению, несколько вложенных разрешений не поддерживаются в Vega-Lite, поэтому делать то, что вы хотите, невозможно. См. github.com/altair-viz/altair/issues/1800 для одного. связанный отчет об ошибке.   -  person jakevdp    schedule 30.10.2020


Ответы (1)


Хорошо, я понял, но это, наверное, не лучшее решение. Я следовал методу, описанному в следующей ссылке, где мы вручную фасетили диаграммы:

  1. Обсуждение аспектов

Чтобы получить двойную ось, я просто добавил .resolve_scale(y='independent') к ручному шагу. Вот решение:

import altair as alt
from vega_datasets import data
import pandas as pd

source = data.anscombe().copy()
source\['line-label'\] = 'x=y'
source = pd.concat(\[source,source.groupby('Series').agg(x_diff=('X','diff'), y_diff=('Y','diff'))\],axis=1)
source\['rate'\] = source.y_diff/source.x_diff
source\['rate-label'\] = 'rate of change'
source\['line-label'\] = 'line y=x'

source_linear = source.groupby(by=\['Series'\]).agg(x_linear=('X','max'), y_linear=('X', 'max')).reset_index().sort_values(by=\['Series'\])

source_origin = source_linear.copy()
source_origin\['y_linear'\] = 0
source_origin\['x_linear'\] = 0

source_linear = pd.concat(\[source_origin,source_linear\]).sort_values(by=\['Series'\])

source = source.merge(source_linear,on='Series').drop_duplicates()

scatter = alt.Chart().mark_circle(size=60, opacity=0.60).encode(
    x=alt.X('X', title='X'),
    y=alt.Y('Y', title='Y'),
    color='Series:N',
    tooltip=\['X','Y','rate'\]
)

line_plot = alt.Chart().mark_line(color= 'black', strokeDash=\[3,8\]).encode(
    x=alt.X('x_linear', title = '', axis=None),
    y=alt.Y('y_linear', title = '', axis=None),
    shape = alt.Shape('line-label', title = 'Break Even'),
    color = alt.value('black')
)

rate =  alt.Chart().mark_line(strokeDash=\[5,3\]).encode(
    x=alt.X('X', title = 'X'),
    y=alt.Y('rate:Q'),
    color = alt.Color('rate-label',),
    tooltip=\['rate','X','Y'\]
)

scatter_rate = alt.layer(scatter, rate, data=source)

chart_generator =  (alt.layer(scatter, rate, line_plot, data = source, title=f"{val}: Duplicated Points w/ Line at Y=X").transform_filter(alt.datum.Series == val).resolve_scale(y='independent') \
             for val in source.Series.unique()) 

chart = alt.concat(*(
    chart_generator
), columns=2).display()

введите описание изображения здесь

person blehman    schedule 30.10.2020