提问人:Lasse Freitag 提问时间:11/15/2023 最后编辑:Trenton McKinneyLasse Freitag 更新时间:11/16/2023 访问量:76
如何根据名称为所有子图中的所有条形着色
How to color all bars in all subplots based off a 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),
)
每个带有“?”的 Bar 都应该是蓝色的,但不是,而 A2 中的 f 是蓝色的,这也是错误的
答:
1赞
kevin41
11/15/2023
#1
问题在于,您正在将颜色映射到列中的每个值,但值可能会出现多次。例如,如果硬编码,则会看到结果是 .A2
cr:=[color(x) for x in df[colname]]
['r', 'b', 'b', 'r', 'r']
但是,您只有 3 个条形,因此仅使用前 3 个颜色值。这就是为什么您会看到 的蓝色 。如果我们只使用列的唯一值来创建颜色映射表,那么列的颜色将按预期进行。f
A2
更改为cr:=[color(x) for x in df[colname]]
cr:=[color(x) for x in df[colname].unique()],
评论
0赞
Trenton McKinney
11/16/2023
不指定色调
而传递调色板
已弃用,并将在 v0.14.0 中删除。将 x
变量分配给 hue
并设置 legend=False
以获得相同的效果。
1赞
Trenton McKinney
11/16/2023
#2
- 不传递而不传递已弃用,因此最好使用 pandas 将 DataFrame 转换为长格式
。DataFrame.melt
,并为颜色添加一列,该列提供了一列,以便轻松创建 的 和 的列。palette
hue
dict
palette
hue
- 这也使使用
sns.catplot
和kind='count'
绘图更容易。
- 这也使使用
- 在
python v3.12.0
、pandas v2.1.2
、matplotlib v3.8.1
、seaborn 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'}
评论