【问题标题】:How to plot a wide dataframe with colors and linestyles based on different columns如何根据不同的列绘制具有颜色和线型的宽数据框
【发布时间】:2023-03-06 04:27:01
【问题描述】:

这是我的一个数据框:

d = {'year': [2020,2020,2020,2021,2020,2020,2021], 
     'month': [10, 11,12,1,11,12,1],
     'class':['A','A','A','A','B','B','B'],
     'val1':[2,3,4,5,1,1,1],
     'val2':[3,3,3,3,2,3,5]}

df = pd.DataFrame(data=d)

输出:

   year  month class  val1  val2
0  2020     10     A     2     3
1  2020     11     A     3     3
2  2020     12     A     4     3
3  2021      1     A     5     3
4  2020     11     B     1     2
5  2020     12     B     1     3
6  2021      1     B     1     5

我需要随着时间的推移以不同的颜色(比如绿色和红色)绘制 val1 和 val2。还有两个类 A 和 B,我想用不同的线型(实线和虚线)绘制这两个类。所以如果类是 A,那么 val1 在图中可能是纯绿色,如果类是 B,那么 val1 在图中可能是绿色虚线。如果 class 是 B,那么 val2 在图中可能是纯红色,如果 class 是 B,那么 val2 在图中可能是红色虚线。

但是我遇到了需要解决的时间(x 轴)问题。首先,时间在不同的列(年和月)中,并且两个类的行数不同。在上面的数据中,B 类直到 2020 年 11 月才开始。

我尝试解决这个问题是使用年份和月份创建新索引:

df.index=df['year']+df['month']/12
df.groupby('class')['val1'].plot(legend='True')
plt.show()

但这会在 x 轴上创建不理想的刻度标签(我想我可以稍后重命名)。虽然它区分了这两个类,但它并没有按照我想要的方式进行。我也不知道如何在图中添加更多列。请指教。谢谢

【问题讨论】:

    标签: python pandas matplotlib seaborn


    【解决方案1】:
    1. 组合'year''month' 列以创建一个带有datetime dtype 的列。
    2. pandas.DataFrame.melt 用于将 DataFrame 从宽格式转换为长格式
    3. 使用seaborn.relplot 绘图,这是一个图形级别的绘图,以简化设置图形的高度和宽度。
    4. 使用mdates 为x 轴提供良好的格式。如果不需要,请删除。
    • 使用pandas 1.2.4seaborn 0.11.1matplotlib 3.4.2 测试。

    导入和转换 DataFrame

    import pandas as pd
    import seaborn as sns
    import matplotlib.dates as mdates  # required for formatting the x-axis dates
    import matplotlib.pyplot as plt  # required for creating the figure when using sns.lineplot; not required for sns.relplot
    
    # combine year and month to create a date column
    df['date'] = pd.to_datetime(df.year.astype(str) + df.month.astype(str), format='%Y%m')
    
    # melt the dataframe into a tidy format
    df = df.melt(id_vars=['date', 'class'], value_vars=['val1', 'val2'])
    

    seaborn.relplot

    # plot with seaborn
    p = sns.relplot(data=df, kind='line', x='date', y='value', hue='variable', style='class', height=4, aspect=2, marker='o')
    
    # format the x-axis - use as needed
    # xfmt = mdates.DateFormatter('%Y-%m')
    # p.axes[0, 0].xaxis.set_major_formatter(xfmt)
    

    seaborn.lineplot

    # set the figure height and width
    fig, ax = plt.subplots(figsize=(8, 4))
    
    # plot with seaborn
    sns.lineplot(data=df, x='date', y='value', hue='variable', style='class', marker='o', ax=ax)
    
    # format the x-axis
    xfmt = mdates.DateFormatter('%Y-%m')
    ax.xaxis.set_major_formatter(xfmt)
    
    # move the legend
    ax.legend(bbox_to_anchor=(1.04, 0.5), loc="center left")
    

    融化df

             date class variable  value
    0  2020-10-01     A     val1      2
    1  2020-11-01     A     val1      3
    2  2020-12-01     A     val1      4
    3  2021-01-01     A     val1      5
    4  2020-11-01     B     val1      1
    5  2020-12-01     B     val1      1
    6  2021-01-01     B     val1      1
    7  2020-10-01     A     val2      3
    8  2020-11-01     A     val2      3
    9  2020-12-01     A     val2      3
    10 2021-01-01     A     val2      3
    11 2020-11-01     B     val2      2
    12 2020-12-01     B     val2      3
    13 2021-01-01     B     val2      5
    

    【讨论】:

      【解决方案2】:

      虽然这可以通过pyplotmatplotlib 完成,但seaborn 等更高级别的界面将大大改善您绘制多个维度的体验。请参阅docs,了解使用 seaborn 标记数据的所有各种方式

      试试:

      import pandas as pd
      import seaborn as sns
      
      df['time'] = df.year + df.month/12
      df1 = pd.wide_to_long(df, stubnames='val', i=['year', 'month', 'class'], j='val_number').reset_index()
      
      sns.lineplot(x='time', y='val', hue='class', size='val_number', data=df1)
      

      数据框现在将采用“长”形式,以允许每个“时间”点的唯一“vals”,以及您可以使用的相关标识符标签。

      情节看起来有点混乱,但那是因为你试图用线图表示多少

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-11-28
        • 2020-01-28
        • 1970-01-01
        • 2018-04-30
        • 2021-02-05
        • 2016-11-18
        • 1970-01-01
        相关资源
        最近更新 更多