如何在同一张图中绘制多个线性回归

问题描述 投票:0回答:2

鉴于以下情况:

import numpy as np
import pandas as pd
import seaborn as sns

np.random.seed(365)
x1 = np.random.randn(50)
y1 = np.random.randn(50) * 100
x2 = np.random.randn(50)
y2 = np.random.randn(50) * 100

df1 = pd.DataFrame({'x1':x1, 'y1': y1})
df2 = pd.DataFrame({'x2':x2, 'y2': y2})

sns.lmplot('x1', 'y1', df1, fit_reg=True, ci = None)
sns.lmplot('x2', 'y2', df2, fit_reg=True, ci = None)

这将创建 2 个独立的图。如何将 df2 中的数据添加到同一图表上?我在网上找到的所有seaborn示例似乎都集中在如何创建相邻图表(例如,通过“hue”和“col_wrap”选项)。另外,我不喜欢使用可能存在附加列的数据集示例,因为这在我正在处理的项目中没有自然含义。

如果需要混合使用 matplotlib/seaborn 函数来实现此目的,如果有人可以帮助说明,我将不胜感激。

python pandas matplotlib seaborn linear-regression
2个回答
12
投票

您可以使用

seaborn
FacetGrid
类来获得所需的结果。 您需要用这些行替换您的绘图调用:

# sns.lmplot('x1', 'y1', df1, fit_reg=True, ci = None)
# sns.lmplot('x2', 'y2', df2, fit_reg=True, ci = None)
df = pd.concat([df1.rename(columns={'x1':'x','y1':'y'})
                .join(pd.Series(['df1']*len(df1), name='df')), 
                df2.rename(columns={'x2':'x','y2':'y'})
                .join(pd.Series(['df2']*len(df2), name='df'))],
               ignore_index=True)

pal = dict(df1="red", df2="blue")
g = sns.FacetGrid(df, hue='df', palette=pal, size=5);
g.map(plt.scatter, "x", "y", s=50, alpha=.7, linewidth=.5, edgecolor="white")
g.map(sns.regplot, "x", "y", ci=None, robust=1)
g.add_legend();

这将产生这个情节:

如果我理解正确的话,这就是您所需要的。

请注意,您需要注意

.regplot
参数,并且可能想要更改我作为示例给出的值。

    行尾的
  • ;
    是抑制命令的输出(我在可见的地方使用 ipython 笔记本)。
  • Docs
    .map()
    方法给出一些解释。本质上,它就是这样做的,将绘图命令与数据映射。然而,它可以与“低级”绘图命令一起使用,例如
    regplot
    ,而不是
    lmlplot
    ,后者实际上是在场景后面调用 regplot。
  • 通常
    plt.scatter
    将采用参数:
    c='none'
    edgecolor='r'
    来制作非填充标记。但是seaborn正在干扰这个过程并强制标记颜色,所以我没有看到一个简单/直接的方法来解决这个问题,而是在seaborn生成情节之后操纵
    ax
    元素,这最好作为一部分来解决另一个问题。

4
投票

选项1:
sns.regplot

  • 在这种情况下,最容易实现的解决方案是使用
    sns.regplot
    ,这是一个轴级函数,因为这不需要组合
    df1
    df2
import pandas as pd
import seaborn
import matplotlib.pyplot as plt

# create the figure and axes
fig, ax = plt.subplots(figsize=(6, 6))

# add the plots for each dataframe
sns.regplot(x='x1', y='y1', data=df1, fit_reg=True, ci=None, ax=ax, label='df1')
sns.regplot(x='x2', y='y2', data=df2, fit_reg=True, ci=None, ax=ax, label='df2')
ax.set(ylabel='y', xlabel='x')
ax.legend()
plt.show()


选项2:
sns.lmplot

  • 根据
    sns.FacetGrid
    ,使用图形级函数比直接使用
    FacetGrid
    更好。
  • df1
    df2
    合并为长格式,然后将
    sns.lmplot
    hue
    参数一起使用。
  • 使用
    seaborn
    时,几乎 始终需要数据采用长格式。
    • 习惯上使用
      pandas.DataFrame.stack
      pandas.melt
      将 DataFrame 从宽格式转换为长格式。
    • 因此,
      df1
      df2
      必须重命名列,并有一个附加的标识列。这允许它们以
      axis=0
      (默认长格式)而不是
      axis=1
      (宽格式)连接。
  • 有多种方法可以组合 DataFrame:
    1. 来自Primeranswer中的组合方法如果组合几个DataFrame就可以了。
    2. 但是,如下所示的函数更适合组合多个 DataFrame。
def fix_df(data: pd.DataFrame, name: str) -> pd.DataFrame:
    """rename columns and add a column"""
    # rename columns to a common name
    data.columns = ['x', 'y']
    # add an identifying value to use with hue
    data['df'] = name
    return data


# create a list of the dataframes
df_list = [df1, df2]

# update the dataframes by calling the function in a list comprehension
df_update_list = [fix_df(v, f'df{i}') for i, v in enumerate(df_list, 1)]

# combine the dataframes
df = pd.concat(df_update_list).reset_index(drop=True)

# plot the dataframe
sns.lmplot(data=df, x='x', y='y', hue='df', ci=None)

注释

  • 此答案使用的包版本:
    • pandas v1.2.4
    • seaborn v0.11.1
    • matplotlib v3.3.4
© www.soinside.com 2019 - 2024. All rights reserved.