Plot multiple bar plots for multiple columns

Viewed 292

I have a dataset that looks roughly like the table below. I need to create a barplot for each column TS1 to TS5 that counts the number of each item in that column. The items are one of the following: NOT_SEEN NOT_ABLE HIGH_BAR and numerical values between 110 and 140 separated by 2 (so 110, 112, 114 etc).

I have found a way to do this which works fine but what I am asking is if there is a way to create a loop or something so I don't have to copy paste the same code 5 times (for the 5 columns)?

This is what I have tried and working:

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)

This below is what I copy 5 times and only change the title (Testing 1, Testing 2 etc) and TS1 TS2.. (in the first line).

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')

Then the following code is below the "5" instances of the above.

ax[1,2].set_visible(False)
plt.show()

I am sure there is a way to do this that is much better but I'm new to all this.

Also, I need to make sure the bars of the barplot are ordered going left to right as: NOT_SEEN NOT_ABLE HIGH_BAR and 110, 112, 114 etc

Using python 2.7 (not my choice unfortunately) and 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      |
+----+------+------+----------+----------+----------+----------+----------+
1 Answers

You can put plotting lines in a function and call it in a for loop automatically changing column, title and axis in each iteration:

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()

enter image description here

Related