【问题标题】:How to plot multiple linear regressions in the same figure如何在同一图中绘制多个线性回归
【发布时间】:2016-07-01 18:29:28
【问题描述】:

鉴于以下情况:

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 中的数据添加到 SAME 图表中?我在网上找到的所有 seaborn 示例似乎都集中在如何创建相邻图形(例如,通过“hue”和“col_wrap”选项)。此外,我不喜欢使用可能存在附加列的数据集示例,因为这在我正在处理的项目中没有自然意义。

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

【问题讨论】:

    标签: python pandas matplotlib plot seaborn


    【解决方案1】:

    您可以使用seabornFacetGrid 类来获得所需的结果。 您需要用这些行替换您的绘图调用:

    # 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 notebook)。
    • Docs.map() 方法做一些解释。本质上,它就是这样做的,将绘图命令与数据映射。但是,它可以使用像 regplot 这样的“低级”绘图命令,而不是 lmlplot,它实际上是在后台调用 regplot。
    • 通常plt.scatter 会使用参数:c='none'edgecolor='r' 来制作未填充的标记。但是 seaborn 干扰了这个过程并对标记强制执行颜色,所以我看不到一个简单/直接的方法来解决这个问题,但是在 seaborn 生成情节之后操纵ax 元素,最好作为一部分解决另一个问题。

    【讨论】:

      【解决方案2】:

      选项 1:sns.regplot

      • 在这种情况下,最容易实现的解决方案是使用sns.regplot,这是一个轴级函数,因为这不需要结合df1df2
      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更好。
      • df1df2 组合成一个长格式,然后将sns.lmplothue 参数一起使用。
      • 使用seaborn 时,几乎总是需要使用长格式的数据。
        • 习惯上使用pandas.DataFrame.stackpandas.melt 将DataFrames 从宽转换为长。
        • 因此,df1df2 必须重命名列,并具有附加的标识列。这允许它们以axis=0(默认长格式)而不是axis=1(宽格式)连接。
      • 有多种方法可以组合 DataFrame:
        1. Primer 中的answer 中的组合方法如果组合几个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

      【讨论】:

        猜你喜欢
        • 2021-07-18
        • 2020-12-16
        • 2013-07-17
        • 1970-01-01
        • 2019-10-20
        • 2020-11-01
        • 1970-01-01
        • 2021-03-18
        • 2020-07-13
        相关资源
        最近更新 更多