Setting a range of values as variables for a barplot - python

Viewed 131

In my data, I have a column that shows either one of the following options: 'NOT_TESTED', 'NOT_COMPLETED', 'TOO_LOW', or a value between 150 and 190 with a step of 5 (so 150, 155, 160 etc).
I am trying to plot a barplot which shows the amount of time each of these appear in the column, including each individual number.
So the barplot should have as variables on the x-axis: 'NOT_TESTED', 'NOT_COMPLETED', 'TOO_LOW', 150, 155, 160 and so on.
The stick height should be the amount of times it appears in the column.
This is the code I have tried and it has gotten me the closest to my goal, however, all the numbers (150-190) output 1 as a value for the barplot, so all the sticks are at the same height.
This does not follow the data and I do not know how to move forward.
I am new to this, any guidance would be greatly appreciated!

num_range = list(range(150,191, 5))
OUTCOMES = ['NOT_TESTED', 'NOT_COMPLETED', 'TOO_LOW']
OUTCOMES.extend(num_range)
df = df.append(pd.DataFrame(num_range, 
       columns=['PT1']),
       ignore_index = True)
df["outcomes_col"] = df["PT1"].astype ("category")
df["outcomes_col"].cat.set_categories(OUTCOMES , inplace = True )
sns.countplot(x= "outcomes_col", data=df, palette='Magma')
plt.xticks(rotation = 90)
plt.ylabel('Amount')
plt.xlabel('Outcomes')
plt.title("Outcomes per Testing")
plt.show()


pd.DataFrame({'ID': {0: 'GF342',  1: 'IF874',  2: 'FH386',  3: 'KJ190',  4: 'TY748',  5: 'YT947',  6: 'DF063',  7: 'ET512',  8: 'GC714',  9: 'SD978',  10: 'EF472',  11: 'PL489',  12: 'AZ315',  13: 'OL821',  14: 'HN765',  15: 'ED589'}, 'Location': {0: 'Q1',  1: 'Q3',  2: 'Q1',  3: 'Q3',  4: 'Q3',  5: 'Q4',  6: 'Q3',  7: 'Q1',  8: 'Q2',  9: 'Q3',  10: 'Q1',  11: 'Q2',  12: 'Q1',  13: 'Q1',  14: 'Q3',  15: 'Q1'}, 'NEW': {0: 'YES',  1: 'NO',  2: 'NO',  3: 'YES',  4: 'YES',  5: 'NO',  6: 'NO',  7: 'YES',  8: 'NO',  9: 'NO',  10: 'NO',  11: 'YES',  12: 'NO',  13: 'YES',  14: 'YES',  15: 'YES'}, 'YEAR': {0: 2021,  1: 2018,  2: 2019,  3: 2021,  4: 2021,  5: 2019,  6: 2019,  7: 2021,  8: 2018,  9: 2019,  10: 2018,  11: 2021,  12: 2018,  13: 2021,  14: 2021,  15: 2021}, 'PT1': {0: '',  1: 'NOT_TESTED',  2: '',  3: 'NOT_FINISHED',  4: '165',  5: '',  6: '180',  7: '145',  8: '155',  9: '',  10: '',  11: '',  12: 'TOO_LOW',  13: '150',  14: '155',  15: ''}, 'PT2': {0: '',  1: '',  2: '',  3: '',  4: '',  5: 'TOO_LOW',  6: '',  7: '',  8: '160',  9: 'TOO_LOW',  10: '',  11: '',  12: '',  13: '',  14: '',  15: ''}, 'PT3': {0: '',  1: 'TOO_LOW',  2: '',  3: 'TOO_LOW',  4: '',  5: '',  6: '',  7: '',  8: '',  9: '',  10: '',  11: 'NOT_FINISHED',  12: '',  13: '185',  14: '',  15: '165'}, 'PT4': {0: '',  1: '',  2: '',  3: '',  4: '',  5: 165.0,  6: '',  7: '',  8: '',  9: '',  10: '',  11: '',  12: 180.0,  13: '',  14: '',  15: ''}})

This not the whole dataset, just part of it.

1 Answers

Starting from this dataframe:
(I replaced NOT_FINISHED with NOT_COMPLETED, compliant to code in your question, let me know if this replacement is correct)

       ID Location  NEW  YEAR            PT1      PT2            PT3  PT4
0   GF342       Q1  YES  2021                                            
1   IF874       Q3   NO  2018     NOT_TESTED                 TOO_LOW     
2   FH386       Q1   NO  2019                                            
3   KJ190       Q3  YES  2021  NOT_COMPLETED                 TOO_LOW     
4   TY748       Q3  YES  2021            165                             
5   YT947       Q4   NO  2019                 TOO_LOW                 165
6   DF063       Q3   NO  2019            180                             
7   ET512       Q1  YES  2021            145                             
8   GC714       Q2   NO  2018            155      160                    
9   SD978       Q3   NO  2019                 TOO_LOW                    
10  EF472       Q1   NO  2018                                            
11  PL489       Q2  YES  2021                          NOT_COMPLETED     
12  AZ315       Q1   NO  2018        TOO_LOW                          180
13  OL821       Q1  YES  2021            150                     185     
14  HN765       Q3  YES  2021            155                             
15  ED589       Q1  YES  2021                                    165     

If you are interested in a count plot of 'PT1' column, first of all you have to define the categories to be plotted. You can use pandas.CategoricalDtype, so you can sort these categories.
So you define a new 'outcomes_col' column:

num_range = list(range(150,191, 5))
OUTCOMES = ['NOT_TESTED', 'NOT_COMPLETED', 'TOO_LOW']
OUTCOMES.extend([str(num) for num in num_range])
OUTCOMES = CategoricalDtype(OUTCOMES, ordered = True)
df["outcomes_col"] = df["PT1"].astype(OUTCOMES)

Then you can proceed to plot this column:

sns.countplot(x= "outcomes_col", data=df, palette='Magma')
plt.xticks(rotation = 90)
plt.ylabel('Amount')
plt.xlabel('Outcomes')
plt.title("Outcomes per Testing")
    
plt.show()

Complete Code

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from pandas.api.types import CategoricalDtype


df = pd.DataFrame({'ID': {0: 'GF342',  1: 'IF874',  2: 'FH386',  3: 'KJ190',  4: 'TY748',  5: 'YT947',  6: 'DF063',  7: 'ET512',  8: 'GC714',  9: 'SD978',  10: 'EF472',  11: 'PL489',  12: 'AZ315',  13: 'OL821',  14: 'HN765',  15: 'ED589'}, 'Location': {0: 'Q1',  1: 'Q3',  2: 'Q1',  3: 'Q3',  4: 'Q3',  5: 'Q4',  6: 'Q3',  7: 'Q1',  8: 'Q2',  9: 'Q3',  10: 'Q1',  11: 'Q2',  12: 'Q1',  13: 'Q1',  14: 'Q3',  15: 'Q1'}, 'NEW': {0: 'YES',  1: 'NO',  2: 'NO',  3: 'YES',  4: 'YES',  5: 'NO',  6: 'NO',  7: 'YES',  8: 'NO',  9: 'NO',  10: 'NO',  11: 'YES',  12: 'NO',  13: 'YES',  14: 'YES',  15: 'YES'}, 'YEAR': {0: 2021,  1: 2018,  2: 2019,  3: 2021,  4: 2021,  5: 2019,  6: 2019,  7: 2021,  8: 2018,  9: 2019,  10: 2018,  11: 2021,  12: 2018,  13: 2021,  14: 2021,  15: 2021}, 'PT1': {0: '',  1: 'NOT_TESTED',  2: '',  3: 'NOT_COMPLETED',  4: '165',  5: '',  6: '180',  7: '145',  8: '155',  9: '',  10: '',  11: '',  12: 'TOO_LOW',  13: '150',  14: '155',  15: ''}, 'PT2': {0: '',  1: '',  2: '',  3: '',  4: '',  5: 'TOO_LOW',  6: '',  7: '',  8: '160',  9: 'TOO_LOW',  10: '',  11: '',  12: '',  13: '',  14: '',  15: ''}, 'PT3': {0: '',  1: 'TOO_LOW',  2: '',  3: 'TOO_LOW',  4: '',  5: '',  6: '',  7: '',  8: '',  9: '',  10: '',  11: 'NOT_COMPLETED',  12: '',  13: '185',  14: '',  15: '165'}, 'PT4': {0: '',  1: '',  2: '',  3: '',  4: '',  5: 165.0,  6: '',  7: '',  8: '',  9: '',  10: '',  11: '',  12: 180.0,  13: '',  14: '',  15: ''}})

num_range = list(range(150,191, 5))
OUTCOMES = ['NOT_TESTED', 'NOT_COMPLETED', 'TOO_LOW']
OUTCOMES.extend([str(num) for num in num_range])
OUTCOMES = CategoricalDtype(OUTCOMES, ordered = True)
df["outcomes_col"] = df["PT1"].astype(OUTCOMES)

sns.countplot(x= "outcomes_col", data=df, palette='Magma')
plt.xticks(rotation = 90)
plt.ylabel('Amount')
plt.xlabel('Outcomes')
plt.title("Outcomes per Testing")

plt.show()

enter image description here

Related