I am working with a data set on Pokemon from
I would like the labels to correspond to the color dictionary defined above, and it looks like I currently have repeating colors. TIA!
Data
- Subset of data. Only
'Generation' == 1
and relevant columns
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
CodePudding user response:
Here's how you can do this:
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()
Yields:
CodePudding user response:
- The point of a visualization is to clearly convey information, so a line plot connecting discrete categories is not an appropriate visualization for this data.
- A bar plot should be used
- Convert the wide dataframe to a long dataframe with melt
- Select the Generation 1 data with Boolean indexing
- Sort the data
- Plot the data with
seaborn.catplot
withkind='bar'
.- Use
colors
as thepalette
forhue
.
- Use
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()
Aggregated Plots
- These plots show the mean of each group
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)
Plot all the lines for each 'Name'
- I don't recommend this option because the visualization is not helpful
# 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')