如何为每组线添加单个图例标签
Posted
技术标签:
【中文标题】如何为每组线添加单个图例标签【英文标题】:How to add a single legend label for each group of lines 【发布时间】:2021-12-06 22:45:18 【问题描述】:我正在使用来自 Kaggle 的 Pokemon 数据集 - 我想针对每种类型绘制统计数据。我创建了一个带有类型名称和相关颜色的颜色常量字典。
COLORS = 'Normal' : '#AAAA77',
'Fire': '#ff4422',
'Water': '#3399ff',
'Electric': '#ffcc33',
'Grass': '#77cc55',
'Ice': '#66ccff',
'Fighting': '#bb5544',
'Poison': '#aa5599',
'Ground': '#ddbb55',
'Flying': '#8899ff',
'Psychic': '#ff5599',
'Bug': '#aabb22',
'Rock': '#bbaa66',
'Ghost': '#6666bb',
'Dragon': '#7766ee',
'Dark': '#775544',
'Steel': '#aaaabb',
'Fairy': '#ee99ee'
目前有这个代码来绘制图表:
def plot_parallel(df, label, colors=COLORS):
plt.figure()
c = None
cmap = None
labels = None
if colors:
labels = list(df[label])
print(labels)
c = [colors[val] for i, val in df[label].iteritems()]
print(c)
else:
cmap = 'Greys'
parallel_coordinates(df, label, color=c, colormap=cmap)
plt.show()
plot_parallel(gen_1[['HP', 'Attack', 'Defense', 'Sp. Atk', 'Sp. Def', 'Speed', 'Type 1']], 'Type 1')
这给出了这个输出(仅绘制 GEN 1):
['Grass', 'Grass', 'Grass', 'Grass', 'Fire', 'Fire', 'Fire', 'Fire', 'Fire', 'Water', 'Water', 'Water', 'Water', 'Bug', 'Bug', 'Bug', 'Bug', 'Bug', 'Bug', 'Bug', 'Normal', 'Normal', 'Normal', 'Normal', 'Normal', 'Normal', 'Normal', 'Normal', 'Poison', 'Poison', 'Electric', 'Electric', 'Ground', 'Ground', 'Poison', 'Poison', 'Poison', 'Poison', 'Poison', 'Poison', 'Fairy', 'Fairy', 'Fire', 'Fire', 'Normal', 'Normal', 'Poison', 'Poison', 'Grass', 'Grass', 'Grass', 'Bug', 'Bug', 'Bug', 'Bug', 'Ground', 'Ground', 'Normal', 'Normal', 'Water', 'Water', 'Fighting', 'Fighting', 'Fire', 'Fire', 'Water', 'Water', 'Water', 'Psychic', 'Psychic', 'Psychic', 'Psychic', 'Fighting', 'Fighting', 'Fighting', 'Grass', 'Grass', 'Grass', 'Water', 'Water', 'Rock', 'Rock', 'Rock', 'Fire', 'Fire', 'Water', 'Water', 'Water', 'Electric', 'Electric', 'Normal', 'Normal', 'Normal', 'Water', 'Water', 'Poison', 'Poison', 'Water', 'Water', 'Ghost', 'Ghost', 'Ghost', 'Ghost', 'Rock', 'Psychic', 'Psychic', 'Water', 'Water', 'Electric', 'Electric', 'Grass', 'Grass', 'Ground', 'Ground', 'Fighting', 'Fighting', 'Normal', 'Poison', 'Poison', 'Ground', 'Ground', 'Normal', 'Grass', 'Normal', 'Normal', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Psychic', 'Bug', 'Ice', 'Electric', 'Fire', 'Bug', 'Bug', 'Normal', 'Water', 'Water', 'Water', 'Water', 'Normal', 'Normal', 'Water', 'Electric', 'Fire', 'Normal', 'Rock', 'Rock', 'Rock', 'Rock', 'Rock', 'Rock', 'Normal', 'Ice', 'Electric', 'Fire', 'Dragon', 'Dragon', 'Dragon', 'Psychic', 'Psychic', 'Psychic', 'Psychic']
['#77cc55', '#77cc55', '#77cc55', '#77cc55', '#ff4422', '#ff4422', '#ff4422', '#ff4422', '#ff4422', '#3399ff', '#3399ff', '#3399ff', '#3399ff', '#aabb22', '#aabb22', '#aabb22', '#aabb22', '#aabb22', '#aabb22', '#aabb22', '#AAAA77', '#AAAA77', '#AAAA77', '#AAAA77', '#AAAA77', '#AAAA77', '#AAAA77', '#AAAA77', '#aa5599', '#aa5599', '#ffcc33', '#ffcc33', '#ddbb55', '#ddbb55', '#aa5599', '#aa5599', '#aa5599', '#aa5599', '#aa5599', '#aa5599', '#ee99ee', '#ee99ee', '#ff4422', '#ff4422', '#AAAA77', '#AAAA77', '#aa5599', '#aa5599', '#77cc55', '#77cc55', '#77cc55', '#aabb22', '#aabb22', '#aabb22', '#aabb22', '#ddbb55', '#ddbb55', '#AAAA77', '#AAAA77', '#3399ff', '#3399ff', '#bb5544', '#bb5544', '#ff4422', '#ff4422', '#3399ff', '#3399ff', '#3399ff', '#ff5599', '#ff5599', '#ff5599', '#ff5599', '#bb5544', '#bb5544', '#bb5544', '#77cc55', '#77cc55', '#77cc55', '#3399ff', '#3399ff', '#bbaa66', '#bbaa66', '#bbaa66', '#ff4422', '#ff4422', '#3399ff', '#3399ff', '#3399ff', '#ffcc33', '#ffcc33', '#AAAA77', '#AAAA77', '#AAAA77', '#3399ff', '#3399ff', '#aa5599', '#aa5599', '#3399ff', '#3399ff', '#6666bb', '#6666bb', '#6666bb', '#6666bb', '#bbaa66', '#ff5599', '#ff5599', '#3399ff', '#3399ff', '#ffcc33', '#ffcc33', '#77cc55', '#77cc55', '#ddbb55', '#ddbb55', '#bb5544', '#bb5544', '#AAAA77', '#aa5599', '#aa5599', '#ddbb55', '#ddbb55', '#AAAA77', '#77cc55', '#AAAA77', '#AAAA77', '#3399ff', '#3399ff', '#3399ff', '#3399ff', '#3399ff', '#3399ff', '#ff5599', '#aabb22', '#66ccff', '#ffcc33', '#ff4422', '#aabb22', '#aabb22', '#AAAA77', '#3399ff', '#3399ff', '#3399ff', '#3399ff', '#AAAA77', '#AAAA77', '#3399ff', '#ffcc33', '#ff4422', '#AAAA77', '#bbaa66', '#bbaa66', '#bbaa66', '#bbaa66', '#bbaa66', '#bbaa66', '#AAAA77', '#66ccff', '#ffcc33', '#ff4422', '#7766ee', '#7766ee', '#7766ee', '#ff5599', '#ff5599', '#ff5599', '#ff5599']
我希望标签与上面定义的颜色字典相对应,看起来我目前有重复的颜色。蒂亚!
数据
数据子集。仅限'Generation' == 1
和相关列
HP,Attack,Defense,Sp. Atk,Sp. Def,Speed,Name,Type 1,Generation
45,49,49,65,65,45,Bulbasaur,Grass,1
60,62,63,80,80,60,Ivysaur,Grass,1
80,82,83,100,100,80,Venusaur,Grass,1
80,100,123,122,120,80,VenusaurMega Venusaur,Grass,1
39,52,43,60,50,65,Charmander,Fire,1
58,64,58,80,65,80,Charmeleon,Fire,1
78,84,78,109,85,100,Charizard,Fire,1
78,130,111,130,85,100,CharizardMega Charizard X,Fire,1
78,104,78,159,115,100,CharizardMega Charizard Y,Fire,1
44,48,65,50,64,43,Squirtle,Water,1
59,63,80,65,80,58,Wartortle,Water,1
79,83,100,85,105,78,Blastoise,Water,1
79,103,120,135,115,78,BlastoiseMega Blastoise,Water,1
45,30,35,20,20,45,Caterpie,Bug,1
50,20,55,25,25,30,Metapod,Bug,1
60,45,50,90,80,70,Butterfree,Bug,1
40,35,30,20,20,50,Weedle,Bug,1
45,25,50,25,25,35,Kakuna,Bug,1
65,90,40,45,80,75,Beedrill,Bug,1
65,150,40,15,80,145,BeedrillMega Beedrill,Bug,1
40,45,40,35,35,56,Pidgey,Normal,1
63,60,55,50,50,71,Pidgeotto,Normal,1
83,80,75,70,70,101,Pidgeot,Normal,1
83,80,80,135,80,121,PidgeotMega Pidgeot,Normal,1
30,56,35,25,35,72,Rattata,Normal,1
55,81,60,50,70,97,Raticate,Normal,1
40,60,30,31,31,70,Spearow,Normal,1
65,90,65,61,61,100,Fearow,Normal,1
35,60,44,40,54,55,Ekans,Poison,1
60,85,69,65,79,80,Arbok,Poison,1
35,55,40,50,50,90,Pikachu,Electric,1
60,90,55,90,80,110,Raichu,Electric,1
50,75,85,20,30,40,Sandshrew,Ground,1
75,100,110,45,55,65,Sandslash,Ground,1
55,47,52,40,40,41,Nidoran♀,Poison,1
70,62,67,55,55,56,Nidorina,Poison,1
90,92,87,75,85,76,Nidoqueen,Poison,1
46,57,40,40,40,50,Nidoran♂,Poison,1
61,72,57,55,55,65,Nidorino,Poison,1
81,102,77,85,75,85,Nidoking,Poison,1
70,45,48,60,65,35,Clefairy,Fairy,1
95,70,73,95,90,60,Clefable,Fairy,1
38,41,40,50,65,65,Vulpix,Fire,1
73,76,75,81,100,100,Ninetales,Fire,1
115,45,20,45,25,20,Jigglypuff,Normal,1
140,70,45,85,50,45,Wigglytuff,Normal,1
40,45,35,30,40,55,Zubat,Poison,1
75,80,70,65,75,90,Golbat,Poison,1
45,50,55,75,65,30,Oddish,Grass,1
60,65,70,85,75,40,Gloom,Grass,1
75,80,85,110,90,50,Vileplume,Grass,1
35,70,55,45,55,25,Paras,Bug,1
60,95,80,60,80,30,Parasect,Bug,1
60,55,50,40,55,45,Venonat,Bug,1
70,65,60,90,75,90,Venomoth,Bug,1
10,55,25,35,45,95,Diglett,Ground,1
35,80,50,50,70,120,Dugtrio,Ground,1
40,45,35,40,40,90,Meowth,Normal,1
65,70,60,65,65,115,Persian,Normal,1
50,52,48,65,50,55,Psyduck,Water,1
80,82,78,95,80,85,Golduck,Water,1
40,80,35,35,45,70,Mankey,Fighting,1
65,105,60,60,70,95,Primeape,Fighting,1
55,70,45,70,50,60,Growlithe,Fire,1
90,110,80,100,80,95,Arcanine,Fire,1
40,50,40,40,40,90,Poliwag,Water,1
65,65,65,50,50,90,Poliwhirl,Water,1
90,95,95,70,90,70,Poliwrath,Water,1
25,20,15,105,55,90,Abra,Psychic,1
40,35,30,120,70,105,Kadabra,Psychic,1
55,50,45,135,95,120,Alakazam,Psychic,1
55,50,65,175,95,150,AlakazamMega Alakazam,Psychic,1
70,80,50,35,35,35,Machop,Fighting,1
80,100,70,50,60,45,Machoke,Fighting,1
90,130,80,65,85,55,Machamp,Fighting,1
50,75,35,70,30,40,Bellsprout,Grass,1
65,90,50,85,45,55,Weepinbell,Grass,1
80,105,65,100,70,70,Victreebel,Grass,1
40,40,35,50,100,70,Tentacool,Water,1
80,70,65,80,120,100,Tentacruel,Water,1
40,80,100,30,30,20,Geodude,Rock,1
55,95,115,45,45,35,Graveler,Rock,1
80,120,130,55,65,45,Golem,Rock,1
50,85,55,65,65,90,Ponyta,Fire,1
65,100,70,80,80,105,Rapidash,Fire,1
90,65,65,40,40,15,Slowpoke,Water,1
95,75,110,100,80,30,Slowbro,Water,1
95,75,180,130,80,30,SlowbroMega Slowbro,Water,1
25,35,70,95,55,45,Magnemite,Electric,1
50,60,95,120,70,70,Magneton,Electric,1
52,65,55,58,62,60,Farfetch'd,Normal,1
35,85,45,35,35,75,Doduo,Normal,1
60,110,70,60,60,100,Dodrio,Normal,1
65,45,55,45,70,45,Seel,Water,1
90,70,80,70,95,70,Dewgong,Water,1
80,80,50,40,50,25,Grimer,Poison,1
105,105,75,65,100,50,Muk,Poison,1
30,65,100,45,25,40,Shellder,Water,1
50,95,180,85,45,70,Cloyster,Water,1
30,35,30,100,35,80,Gastly,Ghost,1
45,50,45,115,55,95,Haunter,Ghost,1
60,65,60,130,75,110,Gengar,Ghost,1
60,65,80,170,95,130,GengarMega Gengar,Ghost,1
35,45,160,30,45,70,Onix,Rock,1
60,48,45,43,90,42,Drowzee,Psychic,1
85,73,70,73,115,67,Hypno,Psychic,1
30,105,90,25,25,50,Krabby,Water,1
55,130,115,50,50,75,Kingler,Water,1
40,30,50,55,55,100,Voltorb,Electric,1
60,50,70,80,80,140,Electrode,Electric,1
60,40,80,60,45,40,Exeggcute,Grass,1
95,95,85,125,65,55,Exeggutor,Grass,1
50,50,95,40,50,35,Cubone,Ground,1
60,80,110,50,80,45,Marowak,Ground,1
50,120,53,35,110,87,Hitmonlee,Fighting,1
50,105,79,35,110,76,Hitmonchan,Fighting,1
90,55,75,60,75,30,Lickitung,Normal,1
40,65,95,60,45,35,Koffing,Poison,1
65,90,120,85,70,60,Weezing,Poison,1
80,85,95,30,30,25,Rhyhorn,Ground,1
105,130,120,45,45,40,Rhydon,Ground,1
250,5,5,35,105,50,Chansey,Normal,1
65,55,115,100,40,60,Tangela,Grass,1
105,95,80,40,80,90,Kangaskhan,Normal,1
105,125,100,60,100,100,KangaskhanMega Kangaskhan,Normal,1
30,40,70,70,25,60,Horsea,Water,1
55,65,95,95,45,85,Seadra,Water,1
45,67,60,35,50,63,Goldeen,Water,1
80,92,65,65,80,68,Seaking,Water,1
30,45,55,70,55,85,Staryu,Water,1
60,75,85,100,85,115,Starmie,Water,1
40,45,65,100,120,90,Mr. Mime,Psychic,1
70,110,80,55,80,105,Scyther,Bug,1
65,50,35,115,95,95,Jynx,Ice,1
65,83,57,95,85,105,Electabuzz,Electric,1
65,95,57,100,85,93,Magmar,Fire,1
65,125,100,55,70,85,Pinsir,Bug,1
65,155,120,65,90,105,PinsirMega Pinsir,Bug,1
75,100,95,40,70,110,Tauros,Normal,1
20,10,55,15,20,80,Magikarp,Water,1
95,125,79,60,100,81,Gyarados,Water,1
95,155,109,70,130,81,GyaradosMega Gyarados,Water,1
130,85,80,85,95,60,Lapras,Water,1
48,48,48,48,48,48,Ditto,Normal,1
55,55,50,45,65,55,Eevee,Normal,1
130,65,60,110,95,65,Vaporeon,Water,1
65,65,60,110,95,130,Jolteon,Electric,1
65,130,60,95,110,65,Flareon,Fire,1
65,60,70,85,75,40,Porygon,Normal,1
35,40,100,90,55,35,Omanyte,Rock,1
70,60,125,115,70,55,Omastar,Rock,1
30,80,90,55,45,55,Kabuto,Rock,1
60,115,105,65,70,80,Kabutops,Rock,1
80,105,65,60,75,130,Aerodactyl,Rock,1
80,135,85,70,95,150,AerodactylMega Aerodactyl,Rock,1
160,110,65,65,110,30,Snorlax,Normal,1
90,85,100,95,125,85,Articuno,Ice,1
90,90,85,125,90,100,Zapdos,Electric,1
90,100,90,125,85,90,Moltres,Fire,1
41,64,45,50,50,50,Dratini,Dragon,1
61,84,65,70,70,70,Dragonair,Dragon,1
91,134,95,100,100,80,Dragonite,Dragon,1
106,110,90,154,90,130,Mewtwo,Psychic,1
106,190,100,154,100,130,MewtwoMega Mewtwo X,Psychic,1
106,150,70,194,120,140,MewtwoMega Mewtwo Y,Psychic,1
100,100,100,100,100,100,Mew,Psychic,1
【问题讨论】:
仅供参考:彻底回答问题非常耗时。如果您的问题已解决,请通过接受最适合您的需求的解决方案表示感谢。✔ 位于答案左上角的 ▲/▼ 箭头下方。如果出现更好的解决方案,则可以接受新的解决方案。如果您的声望超过 15,您还可以使用 ▲/▼ 箭头对答案的有用性进行投票。 如果解决方案不能回答问题,请发表评论。 What should I do when someone answers my question?。谢谢。 【参考方案1】: 可视化的重点是清楚地传达信息,因此连接离散类别的线图不适用于此数据的可视化。 应使用条形图 使用 melt 将宽数据帧转换为长数据帧 使用布尔索引选择第 1 代数据 对数据进行排序 用seaborn.catplot
和kind='bar'
绘制数据。
将colors
用作hue
的palette
。
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
# load the data
df = pd.read_csv('Pokemon.csv')
# specify colors
colors = 'Normal': '#AAAA77', 'Fire': '#ff4422', 'Water': '#3399ff', 'Electric': '#ffcc33', 'Grass': '#77cc55',
'Ice': '#66ccff', 'Fighting': '#bb5544', 'Poison': '#aa5599', 'Ground': '#ddbb55', 'Flying': '#8899ff',
'Psychic': '#ff5599', 'Bug': '#aabb22', 'Rock': '#bbaa66', 'Ghost': '#6666bb', 'Dragon': '#7766ee',
'Dark': '#775544', 'Steel': '#aaaabb', 'Fairy': '#ee99ee'
# create a list of the stats columns
cols = ['HP', 'Attack', 'Defense', 'Sp. Atk', 'Sp. Def', 'Speed']
# melt the dataframe into a long form
sel = df.melt(id_vars=['Name', 'Type 1', 'Generation'], value_vars=cols, var_name='Stats')
# for this example select only generation 1 and sort by Type 1 and Name
g1 = sel[sel.Generation.eq(1)].sort_values(['Type 1', 'Name'])
# plot with seaborn, a high-level api for matplotlib
p = sns.catplot(kind='bar', data=g1, x='Name', y='value', hue='Type 1', palette=colors, row='Stats',
height=4, aspect=5.25, dodge=False, sharey=False)
# add xtick labels for each row if desired
for ax in p.axes.flatten():
ax.tick_params(labelbottom=True)
# rotate the xtick labels
p.set_xticklabels(rotation=90, size=8)
# fix the layout so the full xticklabel will show
p.fig.tight_layout()
# move the legend
sns.move_legend(p, "lower center", bbox_to_anchor=(.5, 1), ncol=3, frameon=False)
# save the figure
p.savefig("pokemon.png")
# show the plot
plt.show()
聚合图
这些图显示了每组的平均值sns.catplot(kind='bar', data=g1, x='Stats', y='value', hue='Type 1', palette=colors, height=4, aspect=5, ci=None)
sns.relplot(kind='line', data=g1, x='Stats', y='value', hue='Type 1', palette=colors, height=4, aspect=5, ci=None)
绘制每个'Name'
的所有行
我不推荐这个选项,因为可视化没有帮助
# use cols from previous section
cols2 = ['Name', 'Type 1', 'Generation'] + cols
gen = df.loc[df.Generation.eq(1), cols2]
# create a figure
fig, ax = plt.subplots(figsize=(20, 4))
# groupby Type1
for type1, data in gen.groupby('Type 1'):
# iterate through each row of data for the given type
for i, row in enumerate(data.iterrows()):
# if it's the first row, include a legend
if i == 0:
row[1][3:].plot(ax=ax, label=type1, color=colors[type1])
# otherwise don't include a legend
else:
row[1][3:].plot(ax=ax, color=colors[type1], label='')
# adjust the margins
ax.margins(x=0)
# move the legend
ax.legend(bbox_to_anchor=(1.02, 1.02), loc='upper left')
【讨论】:
【参考方案2】:您可以这样做:
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = (10,10)
df = pd.read_csv("/kaggle/input/pokemon/Pokemon.csv")
COLORS = 'Normal' : '#AAAA77',
'Fire': '#ff4422',
'Water': '#3399ff',
'Electric': '#ffcc33',
'Grass': '#77cc55',
'Ice': '#66ccff',
'Fighting': '#bb5544',
'Poison': '#aa5599',
'Ground': '#ddbb55',
'Flying': '#8899ff',
'Psychic': '#ff5599',
'Bug': '#aabb22',
'Rock': '#bbaa66',
'Ghost': '#6666bb',
'Dragon': '#7766ee',
'Dark': '#775544',
'Steel': '#aaaabb',
'Fairy': '#ee99ee'
df = df.loc[df["Generation"] == 1]
colors = [COLORS.get(i) for i in df["Type 1"]]
df.index = colors
# In gen 1 special attack and special defense are the same
df.rename(columns="Sp. Atk":"Special", inplace=True)
ax = df[["HP", "Attack", "Defense", "Special", "Speed"]].T.plot(color=colors)
# Remove duplicate legend labels, but maintain colors
l, d = [], set()
for t, line in zip(plt.legend().texts, plt.legend().legendHandles):
if t.__repr__() in d:
continue
d.add(t.__repr__())
l.append((t, line))
ax.get_legend().remove()
flip_colors = v:k for k, v in COLORS.items()
plt.legend([j[1] for j in l], [flip_colors[j[0]._text] for j in l])
plt.show()
产量:
【讨论】:
以上是关于如何为每组线添加单个图例标签的主要内容,如果未能解决你的问题,请参考以下文章