C_London
C_London

Reputation: 33

Multiple Bar Plot using Seaborn

I'm making a barplot using 3 datasets in seaborn, however each datapoint overlays the previous, regardless of if it is now hiding the previous plot. eg:

sns.barplot(x="Portfolio", y="Factor", data=d2,
            label="Portfolio", color="g")

sns.barplot(x="Benchmark", y="Factor", data=d2,
            label="Benchmark", color="b")

sns.barplot(x="Active Exposure", y="Factor", data=d2,
            label="Active", color="r")

ax.legend(frameon=True)
ax.set(xlim=(-.1, .5), ylabel="", xlabel="Sector Decomposition")
sns.despine(left=True, bottom=True)

chart

However, I want it to show green, even if the blue being overlayed is greater. Any ideas?

Upvotes: 3

Views: 5273

Answers (1)

Alex
Alex

Reputation: 7045

Without being able to see your data I can only guess that your dataframe is not in long-form. There's a section on the seaborn tutorial on the expected shape of DataFrames that seaborn is expecting, I'd take a look there for more info, specifically the section on messy data.


Because I can't see your DataFrame I have made some assumptions about it's shape:

import numpy as np
import pandas as pd
import seaborn as sns

df = pd.DataFrame({
    "Factor": list("ABC"),
    "Portfolio": np.random.random(3),
    "Benchmark": np.random.random(3),
    "Active Exposure": np.random.random(3),
})
#    Active Exposure  Benchmark Factor  Portfolio
# 0         0.140177   0.112653      A   0.669687
# 1         0.823740   0.078819      B   0.072474
# 2         0.450814   0.702114      C   0.039068

We can melt this DataFrame to get the long-form data seaborn wants:

d2 = df.melt(id_vars="Factor", var_name="exposure")
#   Factor         exposure     value
# 0      A  Active Exposure  0.140177
# 1      B  Active Exposure  0.823740
# 2      C  Active Exposure  0.450814
# 3      A        Benchmark  0.112653
# 4      B        Benchmark  0.078819
# 5      C        Benchmark  0.702114
# 6      A        Portfolio  0.669687
# 7      B        Portfolio  0.072474
# 8      C        Portfolio  0.039068

Then, finally we can plot out box plot using the seaborn's builtin aggregations:

ax = sns.barplot(x="value", y="Factor", hue="exposure", data=d2)
ax.set(ylabel="", xlabel="Sector Decomposition")
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

Which produces:

Example barplot with categorical y axis


Here's the plot params I used to make this chart:

import matplotlib as mpl

# Plot configuration
mpl.style.use("seaborn-pastel")
mpl.rcParams.update(
    {
        "font.size": 14,
        "figure.facecolor": "w",
        "axes.facecolor": "w",
        "axes.spines.right": False,
        "axes.spines.top": False,
        "axes.spines.bottom": False,
        "xtick.top": False,
        "xtick.bottom": False,
        "ytick.right": False,
        "ytick.left": False,
    }
)

If you are fine without using seaborn you can use pandas plotting to create a stacked horizontal bar chart (barh):

import pandas as pd
import matplotlib as mpl

# Plot configuration
mpl.style.use("seaborn-pastel")
mpl.rcParams.update(
    {
        "font.size": 14,
        "figure.facecolor": "w",
        "axes.facecolor": "w",
        "axes.spines.right": False,
        "axes.spines.top": False,
        "axes.spines.bottom": False,
        "xtick.top": False,
        "xtick.bottom": False,
        "ytick.right": False,
        "ytick.left": False,
    }
)

df = pd.DataFrame({
    "Factor": list("ABC"),
    "Portfolio": [0.669687, 0.072474, 0.039068],
    "Benchmark": [0.112653, 0.078819, 0.702114],
    "Active Exposure": [0.140177, 0.823740, 0.450814],
}).set_index("Factor")

ax = df.plot.barh(stacked=True)
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
ax.set_ylabel("")
ax.set_xlabel("Sector Decomposition")

stacked horizontal bar chart

Notice in the code above the index is set to Factor which then becomes the y axis.

If you don't set stacked=True you get almost the same chart as seaborn produced:

ax = df.plot.barh(stacked=False)
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
ax.set_ylabel("")
ax.set_xlabel("Sector Decomposition")

horizontal bar chart

Upvotes: 4

Related Questions