Altair regression transform with params=True: how to access r² and coeffs when having multiple groups

Viewed 332

I am using transform_regression to create a regression line and the corresponding equation text in the chart. For a single regression this works fine, but with set groupby=['something'] option, the texts get plotted on top of each other.

I tried constructing the string using lineBreak='\n' but that didn't help. Also it is creating a own color group for the equations named undefined, which is not very practical. Any way to avoid this? I am aware of this question, but I don't want to change the name, I'd prefer to not give it an own entry at all.

Here is an example:

import altair as alt
import altair_transform
import pandas as pd
import numpy as np

np.random.seed(42)
x = np.linspace(0, 10)
y = np.e ** (-0.1 *x)  + np.random.randn(len(x)) / 5
group = np.random.choice(['a','b'],len(x))

df = pd.DataFrame({'x': x, 'y': y, 'group': group})
df.loc[df.group == 'a', 'y'] *= 0.1 

chart = alt.Chart(df).mark_point().encode(
    x='x',
    y= alt.Y('y',scale = alt.Scale(type= 'log')),
    color= 'group')

Reg_Line = chart.transform_regression('x', 'y',
                                      method="exp",
                                      groupby=["group"]
).mark_line()

Reg_Params = chart.transform_regression('x', 'y',
                                     method="exp",
                                     groupby=["group"],
                                     params=True   
).mark_text(align='left', lineBreak='\n'
).encode(
    x=alt.value(150),  # pixels from left
    y=alt.value(250),  # pixels from top
    text='params:N'
).transform_calculate(
    params='"r² = " + round(datum.rSquared * 100)/100 + \
    "      y = " + round(datum.coef[0] * 10)/10 + " + e ^ (" + \
    round(datum.coef[1] * 10000)/10000 + "x" + ")" + \n + " "')

chart + Reg_Line + Reg_Params

plot

1 Answers

!! This only addresses a part of the question !!

If I find a solution to the rest of the problem I will modify this answer.

While I haven't found a way to resolve placement of texts on top of each other, here is at least something that suppresses the extra legend entry:

  • add a color encoding to the line chart and the text chart and set their legend option to None
  • resolve the colors of the compound with independent

This is a modification of the above example:

import altair as alt
import altair_transform
import pandas as pd
import numpy as np

np.random.seed(42)
x = np.linspace(0, 10)
y = np.e ** (-0.1 *x)  + np.random.randn(len(x)) / 5
group = np.random.choice(['a','b'],len(x))

df = pd.DataFrame({'x': x, 'y': y, 'group': group})
df.loc[df.group == 'a', 'y'] *= 0.1 

chart = alt.Chart(df).mark_point().encode(
    x='x',
    y= alt.Y('y',scale = alt.Scale(type= 'log')),
    color= 'group')

Reg_Line = chart.transform_regression('x', 'y',
                                      method="exp",
                                      groupby=["group"]
).mark_line().encode(color=alt.Color('group', legend=None))

Reg_Params = chart.transform_regression('x', 'y',
                                     method="exp",
                                     groupby=["group"],
                                     params=True   
).mark_text(align='left', lineBreak='\n'
).encode(
    x=alt.value(150),  # pixels from left
    y=alt.value(250),  # pixels from top
    color=alt.Color('group', legend=None),
    text='params:N'
).transform_calculate(
    params='"r² = " + round(datum.rSquared * 100)/100 + \
    "      y = " + round(datum.coef[0] * 10)/10 + " + e ^ (" + \
    round(datum.coef[1] * 10000)/10000 + "x" + ")" + \n + " "')

(chart + Reg_Line + Reg_Params).resolve_scale(color='independent')
Related