Маркеры графика, указывающие значение net для сгруппированной гистограммы в Альтаире - PullRequest
1 голос
/ 28 апреля 2020

У меня есть сгруппированная гистограмма здесь , Python с использованием пакета Altair с положительными и отрицательными значениями. Как я могу построить маркер, чтобы указать значение Net для каждого бара? График здесь использует маркер красной линии, но ромб или точка будут в порядке.

df1=pd.DataFrame(10*np.random.rand(4,3),index=["A","B","C","D"],columns=["I","J","K"])
print(df1)
df2=pd.DataFrame(-10*np.random.rand(4,3),index=["A","B","C","D"],columns=["I","J","K"])
df3=pd.DataFrame(10*np.random.rand(4,3),index=["A","B","C","D"],columns=["I","J","K"])

def prep_df(df, name):
    df = df.stack().reset_index()
    df.columns = ['c1', 'c2', 'values']
    df['DF'] = name
    return df

df1 = prep_df(df1, 'DF1')
df2 = prep_df(df2, 'DF2')
df3 = prep_df(df3, 'DF3')

df = pd.concat([df1, df2, df3])

alt.Chart(df).mark_bar().encode(

    # tell Altair which field to group columns on
    x=alt.X('c2:N', title=None),

    # tell Altair which field to use as Y values and how to calculate
    y=alt.Y('sum(values):Q',
        axis=alt.Axis(
            grid=False,
            title=None)),

    # tell Altair which field to use to use as the set of columns to be  represented in each group
    column=alt.Column('c1:N', title=None),

    # tell Altair which field to use for color segmentation
    color=alt.Color('DF:N',
            scale=alt.Scale(
                # make it look pretty with an enjoyable color pallet
                range=['#96ceb4', '#ffcc5c','#ff6f69'],
            ),
        ))\
    .configure_view(
        # remove grid lines around column clusters
        strokeOpacity=0
    )

Я пытался вычислить "Net" в отдельном df, затем делал что-то вроде:

tick = alt.Chart(source).mark_tick(
    color='red',
    thickness=2,
    size=40 * 0.9,  # controls width of tick.
).encode(
    x=alt.X('c2:N', title=None),
    y=alt.Y('Net')
)

, но ошибка: 'Net' не определена

1 Ответ

0 голосов
/ 28 апреля 2020

Нет необходимости предварительно вычислять сумму; Альтаир может сделать это напрямую. Хитрость заключается в том, что многогранные диаграммы не могут быть многослойными, поэтому вы должны вместо этого огранить многослойную диаграмму:

base = alt.Chart(df).encode(
    x=alt.X('c2:N', title=None),
    y=alt.Y('sum(values):Q',
        axis=alt.Axis(
            grid=False,
            title=None)),
)

bars = base.mark_bar().encode(
    color=alt.Color('DF:N',
            scale=alt.Scale(
                range=['#96ceb4', '#ffcc5c','#ff6f69'],
            ),
        )
)

net = base.mark_tick(
    color='red',
    thickness=2,
    size=18,
)

alt.layer(bars, net).facet(
    column=alt.Column('c1:N', title=None)
).configure_view(
    strokeOpacity=0
)

enter image description here

...