matplotlib 基于两个Pandas数据框列(连续值和标记样式)进行可视化

i7uq4tfw  于 2023-02-23  发布在  其他
关注(0)|答案(1)|浏览(151)

I would like to visualize a dataset (with legend and color bar). The dataset is a pandas dataframe as follows: X and Y are the values, the year column defines the year of data collection, and the shape column defines the method that is used in data collection. I am wondering how I can plot Y against X while color-coded based on years and markers (and therefore legend) defined by shape in one command such as plot.

df = pd.DataFrame({
    'X':     [1,    1,    2,    2,    2,    3,    3,    4],
    'Y':     [3,    4,    1,    6,    7,    8,    8,    5],
    'year':  [1998, 1999, 1994, 1991, 1999, 1995, 1994, 1992],
    'shape': ['o',  '^',  'o',  '^',  'o',  '^',  'o',  '^']
})

Of course, I can loop over the shapes and plot per shape (method) and add a color bar separately as well ensuring the min and max of the years in the color bar and legend based on shape. I would like to avoid loop and manual setting of legend or color bar if possible. I am wondering if there is a better way forward. Thank you!
Edit:
I am after sth like this based on the answer provided below by Tranbi, I need both legend and color bar:

kb5ga3dv

kb5ga3dv1#

This sounds like a job for seaborn:

import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
import matplotlib.lines as mlines

df = pd.DataFrame({
    'X':     [1,    1,    2,    2,    2,    3,    3,    4],
    'Y':     [3,    4,    1,    6,    7,    8,    8,    5],
    'year':  [1998, 1999, 1994, 1991, 1999, 1995, 1994, 1992],
    'method':['A',  'B',  'A',  'C',  'A',  'B',  'A',  'B'],
    'shape': ['o',  '^',  'o',  '*',  'o',  '^',  'o',  '^']
})

palette = 'viridis'

ax = sns.scatterplot(data=df, x='X', y='Y',
                hue='year',
                palette=palette,
                style='shape',
                markers=df['shape'].unique().tolist(),
                legend=False
)
# build legend
lines = [mlines.Line2D([], [], marker=shape, label=method, linestyle='None')
        for shape, method in 
        df[['shape', 'method']].drop_duplicates()
        .sort_values('method').itertuples(index=False)]
ax.legend(handles=lines)

# build colorbar
norm = plt.Normalize(df['year'].min(), df['year'].max())
sm = plt.cm.ScalarMappable(cmap=palette, norm=norm)
ax.figure.colorbar(sm, ax=ax)

plt.show()

Output:

Edit: adding legend and colormap
Edit2: adding method column + changing color palette

相关问题