matplotlib 如何根据名称为所有子图中的所有条形图着色

svmlkihl  于 2023-11-22  发布在  其他
关注(0)|答案(2)|浏览(124)

我们的目标是用不同颜色的“?”来标记每一个酒吧。类似的问题之前已经被问过了,但它并没有解决我在这里面临的问题。
How to color a single bar based off name

%matplotlib inline

import pandas as pd
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns

data=[['a','a','b'],[20,'?',18],['?','?','f'],['?','f','f'],['a','a','?']]
col_with_missting_values=['A1','A2','A3']
df=pd.DataFrame(data,columns=col_with_missting_values)

def color(coln):
    if coln=='?':
        return 'b'
    else:
        return 'r'

fig, axes = plt.subplots(1, len(col_with_missting_values), figsize=(20, 5))
for colname, ax in zip(col_with_missting_values, axes):
    (
        cr:=[color(x) for x in df[colname]],
        sns.countplot(df, x=f"{colname}", ax=ax, palette=cr),
        ax.set_xticklabels(ax.get_xticklabels(), rotation=90),
    )

字符串
每一个有“?”的条形图都应该是蓝色的,但实际上不是,而A2中的f是蓝色的,这也是错误的。


的数据

4uqofj5v

4uqofj5v1#

这个问题是因为你将一种颜色Map到一列中的每个值,但是一个值可能会出现多次。例如,如果你在cr:=[color(x) for x in df[colname]]中硬编码A2,你会看到结果是['r', 'b', 'b', 'r', 'r']
但是,你只有3个条,所以只使用前3个颜色值。这就是为什么你看到A2f显示为蓝色。如果我们只使用列的唯一值来创建颜色图,那么列的颜色就像你期望的那样。
cr:=[color(x) for x in df[colname]]更改为cr:=[color(x) for x in df[colname].unique()],
结果:

n3schb8v

n3schb8v2#

  • 传递palette而不传递hue是不推荐的,所以最好用pandas.DataFrame.melt将字符串转换为长格式,并为颜色添加一列,这为palettehue提供了一列,以便轻松创建dict
  • 这也使sns.catplotkind='count'的打印更容易。
    *python v3.12.0pandas v2.1.2matplotlib v3.8.1seaborn v0.13.0中测试。
import pandas as pd
import seaborn as sns
import numpy as np

# sample data from OP
data = [['a', 'a', 'b'], [20, '?', 18], ['?', '?', 'f'],
        ['?', 'f', 'f'], ['a', 'a', '?']]
cols = ['A1', 'A2', 'A3']
df = pd.DataFrame(data, columns=cols)

# convert the data to long form as required by seaborn
dfm = df.melt(var_name='variable', value_name='value')

# add a palette column
dfm['palette'] = np.where(dfm['value'].eq('?'), 'b', 'r')

# create a palette dictionary
palette = dict(dfm[['value', 'palette']].values)

# plot the data
g = sns.catplot(kind='count', data=dfm, x='value', col='variable', sharex=False,
                hue='value', palette=palette, legend=False, height=5, aspect=1)

# remove 'variable = ' from facet title if preferred
g.set_titles(template='{col_name}')

# remove xlabels if preferred
g.set(xlabel='')

# rotate xticklabels if preferred
_ = g.set_xticklabels(rotation=30)

字符串


的数据

dfm.head()

variable value palette
0       A1     a       r
1       A1    20       r
2       A1     ?       b
3       A1     ?       b
4       A1     a       r

palette

{'a': 'r', 20: 'r', '?': 'b', 'f': 'r', 'b': 'r', 18: 'r'}

相关问题