使用seaborn.swarmplot将数据映射到colormap

时间:2016-11-26 03:23:55

标签: python pandas matplotlib seaborn

我想生成一个seaborn.swarmplot,其中单个数据点的颜色被映射到颜色映射。

我有一个类似于此的DataFrame:

In[48]:df
Out[48]: 
      a  c   Key
   0  1  12  1st
   1  4  35  2nd
   2  5  12  2nd
   3  6  46  1st
   4  3  78  1st
   5  4  45  2nd
   6  5  34  1st
   7  6  70  2nd

我使用以下代码生成一个swarmplot:

sns.swarmplot(x='Key', y = 'a',  s=20, data = df)

得到这样的情节:

Swarmplot

现在,我想将数据点映射到色彩映射,该色彩映射表示根据DataFrame的列“c”的值。

我尝试在代码中添加'hue ='c'并获得以下内容:

sns.swarmplot(x='Key', y = 'a',  hue='c',s=20, data = df)

Swarmplot with 'hue'

这种方式朝着我想要的方向发展,但我更倾向于将颜色贴图设置为颜色贴图,因此低'c'值例如是浅绿色,并且''更高'' c'值得到绿色越深。

作为一个传奇,我想要一个渐变。

非常感谢帮助!!!

1 个答案:

答案 0 :(得分:6)

Solution without colorbar

The solution without colorbar is rather easy. You need to create a palette of colors (with as many colors as values) and supply it to the swarmplot using the palette argument.

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
print sns.__version__ # swarmplot requires version 0.7.1

# Reconstruct the dataframe from the question (the hardest part)
a = [1,4,5,6,3,4,5,6]
c = [12,35,12,46,78,45,34,70]
key = [1,2,2,1,1,2,1,2]
key = ["{k}{a}".format(k=k, a={1:"st", 2:"nd"}[k]) for k in key]
df  =pd.DataFrame({"a":a, "c":c, "Key":key})

palette = sns.light_palette("seagreen", reverse=False,  n_colors=len(c) )
sns.swarmplot(x='Key', y = 'a',  hue='c',s=20, data = df, palette=palette)

plt.show()

enter image description here


Solution with colorbar

The solution with colorbar requires more work. We need to construct a colormap from the seaborn palette, normalize this colormap and create a dictionary of colors corresponding to the respective colors from the df["c"] dataframe column. We then provide this dictionary to the swarmplot using again the palette keyword.

We also need to remove the automatically generated, but useless legend and then create a new axes in the plot to place the colorbar.

import pandas as pd

import matplotlib.pyplot as plt
import matplotlib.colorbar
import matplotlib.colors
import matplotlib.cm
from mpl_toolkits.axes_grid1 import make_axes_locatable

import seaborn as sns

# recreate the dataframe
a = [1,4,5,6,3,4,5,6]
c = [12,35,12,46,78,45,34,70]
key = [1,2,2,1,1,2,1,2]
key = ["{k}{a}".format(k=k, a={1:"st", 2:"nd"}[k]) for k in key]
df  =pd.DataFrame({"a":a, "c":c, "Key":key})

#Create a matplotlib colormap from the sns seagreen color palette
cmap    = sns.light_palette("seagreen", reverse=False, as_cmap=True )
# Normalize to the range of possible values from df["c"]
norm = matplotlib.colors.Normalize(vmin=df["c"].min(), vmax=df["c"].max())
# create a color dictionary (value in c : color from colormap) 
colors = {}
for cval in df["c"]:
    colors.update({cval : cmap(norm(cval))})

#create a figure
fig = plt.figure(figsize=(5,2.8))
#plot the swarmplot with the colors dictionary as palette
m = sns.swarmplot(x='Key', y = 'a',  hue="c", s=20, data = df, palette = colors)
# remove the legend, because we want to set a colorbar instead
plt.gca().legend_.remove()

## create colorbar ##
divider = make_axes_locatable(plt.gca())
ax_cb = divider.new_horizontal(size="5%", pad=0.05)
fig.add_axes(ax_cb)
cb1 = matplotlib.colorbar.ColorbarBase(ax_cb, cmap=cmap,
                                norm=norm,
                                orientation='vertical')
cb1.set_label('Some Units')
plt.show()

enter image description here