为多列绘制多个条形图
Posted
技术标签:
【中文标题】为多列绘制多个条形图【英文标题】:Plot multiple bar plots for multiple columns 【发布时间】:2021-11-03 00:24:30 【问题描述】:我有一个大致如下表的数据集。
我需要为TS1
到TS5
的每一列创建一个条形图,计算该列中每个项目的数量。这些项目是以下之一:NOT_SEEN
NOT_ABLE
HIGH_BAR
和 110
和 140
之间的数值,用 2 分隔(所以 110
、112
、114
等)。
我找到了一种方法可以很好地做到这一点,但我要问的是是否有一种方法可以创建循环或其他东西,所以我不必复制粘贴相同的代码 5 次(对于 5 列)?
这是我尝试过的工作:
num_range = list(range(110,140, 2))
OUTCOMES = ['NOT_SEEN', 'NOT_ABLE', 'HIGH_BAR']
OUTCOMES.extend([str(num) for num in num_range])
OUTCOMES = CategoricalDtype(OUTCOMES, ordered = True)
fig, ax =plt.subplots(2, 3, sharey=True)
fig.tight_layout(pad=3)
这是我复制 5 次的内容,只更改了标题(Testing 1
、Testing 2
等)和TS1
TS2
..(在第一行)。
df["outcomes"] = df["TS1"].astype(OUTCOMES)
bpt=sns.countplot(x= "outcomes", data=df, palette='GnBu', ax=ax[0,0])
plt.setp(bpt.get_xticklabels(), rotation=60, size=6, ha='right')
bpt.set(xlabel='')
bpt.set_title('Testing 1')
那么下面的代码在上面的“5”个实例下面。
ax[1,2].set_visible(False)
plt.show()
我确信有一种更好的方法可以做到这一点,但我对这一切都很陌生。
另外,我需要确保条形图的条从左到右排列为:NOT_SEEN
NOT_ABLE
HIGH_BAR
和 110
、112
、114
等
使用 python 2.7(很遗憾不是我的选择)和 pandas 0.24.2。
+----+------+------+----------+----------+----------+----------+----------+
| ID | VIEW | YEAR | TS1 | TS2 | TS3 | TS4 | TS5 |
+----+------+------+----------+----------+----------+----------+----------+
| AA | NO | 2005 | | 134 | | HIGH_BAR | |
+----+------+------+----------+----------+----------+----------+----------+
| AB | YES | 2015 | | | NOT_SEEN | | |
+----+------+------+----------+----------+----------+----------+----------+
| AB | YES | 2010 | 118 | | | | NOT_ABLE |
+----+------+------+----------+----------+----------+----------+----------+
| BB | NO | 2020 | | | | | |
+----+------+------+----------+----------+----------+----------+----------+
| BA | YES | 2020 | | | | NOT_SEEN | |
+----+------+------+----------+----------+----------+----------+----------+
| AA | NO | 2010 | | | | | |
+----+------+------+----------+----------+----------+----------+----------+
| BA | NO | 2015 | | | | | 132 |
+----+------+------+----------+----------+----------+----------+----------+
| BB | YES | 2010 | | HIGH_BAR | | 140 | NOT_ABLE |
+----+------+------+----------+----------+----------+----------+----------+
| AA | YES | 2020 | | | | | |
+----+------+------+----------+----------+----------+----------+----------+
| AB | NO | 2010 | | | | 112 | |
+----+------+------+----------+----------+----------+----------+----------+
| AB | YES | 2015 | | | NOT_ABLE | | HIGH_BAR |
+----+------+------+----------+----------+----------+----------+----------+
| BB | NO | 2020 | | | | 145 | |
+----+------+------+----------+----------+----------+----------+----------+
| BA | NO | 2015 | | 110 | | | |
+----+------+------+----------+----------+----------+----------+----------+
| AA | YES | 2010 | HIGH_BAR | | | NOT_SEEN | |
+----+------+------+----------+----------+----------+----------+----------+
| BA | YES | 2015 | | | | | |
+----+------+------+----------+----------+----------+----------+----------+
| AA | NO | 2020 | | | | 118 | |
+----+------+------+----------+----------+----------+----------+----------+
| BA | YES | 2015 | | 180 | NOT_ABLE | | |
+----+------+------+----------+----------+----------+----------+----------+
| BB | YES | 2020 | | NOT_SEEN | | | 126 |
+----+------+------+----------+----------+----------+----------+----------+
【问题讨论】:
仅供参考:彻底回答问题非常耗时。如果您的问题已解决,请通过接受最适合您的需求的解决方案表示感谢。 ✔ 位于答案左上角的 ▲ / ▼ 箭头下方。如果出现更好的解决方案,则可以接受新的解决方案。如果您有 15 岁以上的声誉,您也可以使用 ▲ / ▼ 箭头对答案的有用性进行投票。 如果解决方案不能回答问题,请发表评论。 What should I do when someone answers my question?。谢谢 【参考方案1】:您可以将绘图线放在一个函数中,并在 for 循环中调用它,在每次迭代中自动更改列、标题和轴:
fig, axes =plt.subplots(2, 3, sharey=True)
fig.tight_layout(pad=3)
def plotting(column, title, ax):
df["outcomes"] = df[column].astype(OUTCOMES)
bpt=sns.countplot(x= "outcomes", data=df, palette='GnBu', ax=ax)
plt.setp(bpt.get_xticklabels(), rotation=60, size=6, ha='right')
bpt.set(xlabel='')
bpt.set_title(title)
columns = ['TS1', 'TS2', 'TS3', 'TS4', 'TS5']
titles = ['Testing 1', 'Testing 2', 'Testing 3', 'Testing 4', 'Testing 5']
for column, title, ax in zip(columns, titles, axes.flatten()):
plotting(column, title, ax)
axes[1,2].set_visible(False)
plt.show()
【讨论】:
【参考方案2】:您可以使用seaborn.catplot
避免循环,这允许您将多个countplot
s 绘制到FacetGrid
上。
这是用 python 2.7.18 测试的(尽管它仍然适用于 python 3):
melt
将TS
数据转换成long form:
melted = df.melt(id_vars=[], value_vars=['TS1','TS2','TS3','TS4','TS5'],
var_name='testing', value_name='outcome')
# testing outcome
# 0 TS1 NaN
# 1 TS1 NaN
# 2 TS1 118
# 3 TS1 NaN
# .. ... ...
# 88 TS5 NaN
# 89 TS5 126
通过catplot
绘制melted
数据:
g = sns.catplot(kind='count', x='outcome', col='testing',
col_wrap=3, order=OUTCOMES.categories,
data=melted, palette='GnBu_r')
g.set_xticklabels(rotation=90)
版本:
>>> sys.version
# 2.7.18 (default, Mar 15 2021, 14:29:03) \n[GCC 10.2.0]
>>> pandas.__version__
# 0.24.2
>>> matplotlib.__version__
# 2.2.5
>>> seaborn.__version__
# 0.9.1
【讨论】:
以上是关于为多列绘制多个条形图的主要内容,如果未能解决你的问题,请参考以下文章