3

I have a dataframe with both positive and negative values. I would like to show a bar chart that shows two bars, one bar shows the percentage of positive values and another percentage of negative values.

dummy = pd.DataFrame({'A' : [-4, -3, -1, 0, 1, 2, 3, 4, 5], 'B' : [-4, -3, -1, 0, 1, 2, 3, 4, 5]})
less_than_0 = dummy['A'][dummy['A'] < 0]
greater_than_0 = dummy['A'][dummy['A'] >= 0]

I am able to split the positive and negative values. I tried this using seaborn.

sns.barplot(dummy['A'])

but both positive and negative are coming in single bar. I tried this too

sns.barplot(less_than_0)
sns.barplot(greater_than_0)

Is there any way to show 2 bars, 1 for percentage of positive values and other for percentage of negative values?

JSVJ
  • 500
  • 3
  • 14

2 Answers2

2

This isn't the most elegant solution, but you can create a new DataFrame that contains two columns: labels that contain the labels you want to display on the x-axis of the barplot, and percentages that contain the percentages of negative and positive values.

Then you can pass these column names with the relevant information to sns.barplot as the x and y parameters.

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

dummy = pd.DataFrame({'A' : [-4, -3, -1, 0, 1, 2, 3, 4, 5], 'B' : [-4, -3, -1, 0, 1, 2, 3, 4, 5]})

df_percentages = pd.DataFrame({
    'labels':['Less than 0', 'Greater than or equal to 0'],
    'percentage':[100*x/len(dummy['A']) for x in [sum(dummy['A'] < 0), sum(dummy['A']>=0)]]
    })

sns.barplot(x='labels', y='percentage', data=df_percentages)
plt.show()

enter image description here

Derek O
  • 16,770
  • 4
  • 24
  • 43
1

You can use Series.value_counts with normalize=True and then plot Series:

d = {True:'Less than 0',False:'Greater than or equal to 0'}
s = (dummy['A'] < 0).value_counts(normalize=True).rename(d)
print (s)
Greater than or equal to 0    0.666667
Less than 0                   0.333333
Name: A, dtype: float64

sns.barplot(x=s.index, y=s.to_numpy())
jezrael
  • 822,522
  • 95
  • 1,334
  • 1,252