Reputation: 747
I'm trying to create a density plot in python using Seaborn. I would like the density plot to have one fill color that is different from the line color. Here is an example of what I am trying to create:
And here is the dataframe that I am using:
mtcars = pd.DataFrame.from_dict({'Unnamed: 0': {0: 'Mazda RX4', 1: 'Mazda RX4 Wag', 2: 'Datsun 710', 3: 'Hornet 4 Drive', 4: 'Hornet Sportabout', 5: 'Valiant', 6: 'Duster 360', 7: 'Merc 240D', 8: 'Merc 230', 9: 'Merc 280', 10: 'Merc 280C', 11: 'Merc 450SE', 12: 'Merc 450SL', 13: 'Merc 450SLC', 14: 'Cadillac Fleetwood', 15: 'Lincoln Continental', 16: 'Chrysler Imperial', 17: 'Fiat 128', 18: 'Honda Civic', 19: 'Toyota Corolla', 20: 'Toyota Corona', 21: 'Dodge Challenger', 22: 'AMC Javelin', 23: 'Camaro Z28', 24: 'Pontiac Firebird', 25: 'Fiat X1-9', 26: 'Porsche 914-2', 27: 'Lotus Europa', 28: 'Ford Pantera L', 29: 'Ferrari Dino', 30: 'Maserati Bora', 31: 'Volvo 142E'}, 'mpg': {0: 21.0, 1: 21.0, 2: 22.8, 3: 21.4, 4: 18.7, 5: 18.1, 6: 14.3, 7: 24.4, 8: 22.8, 9: 19.2, 10: 17.8, 11: 16.4, 12: 17.3, 13: 15.2, 14: 10.4, 15: 10.4, 16: 14.7, 17: 32.4, 18: 30.4, 19: 33.9, 20: 21.5, 21: 15.5, 22: 15.2, 23: 13.3, 24: 19.2, 25: 27.3, 26: 26.0, 27: 30.4, 28: 15.8, 29: 19.7, 30: 15.0, 31: 21.4}, 'cyl': {0: 6, 1: 6, 2: 4, 3: 6, 4: 8, 5: 6, 6: 8, 7: 4, 8: 4, 9: 6, 10: 6, 11: 8, 12: 8, 13: 8, 14: 8, 15: 8, 16: 8, 17: 4, 18: 4, 19: 4, 20: 4, 21: 8, 22: 8, 23: 8, 24: 8, 25: 4, 26: 4, 27: 4, 28: 8, 29: 6, 30: 8, 31: 4}, 'disp': {0: 160.0, 1: 160.0, 2: 108.0, 3: 258.0, 4: 360.0, 5: 225.0, 6: 360.0, 7: 146.7, 8: 140.8, 9: 167.6, 10: 167.6, 11: 275.8, 12: 275.8, 13: 275.8, 14: 472.0, 15: 460.0, 16: 440.0, 17: 78.7, 18: 75.7, 19: 71.1, 20: 120.1, 21: 318.0, 22: 304.0, 23: 350.0, 24: 400.0, 25: 79.0, 26: 120.3, 27: 95.1, 28: 351.0, 29: 145.0, 30: 301.0, 31: 121.0}, 'hp': {0: 110, 1: 110, 2: 93, 3: 110, 4: 175, 5: 105, 6: 245, 7: 62, 8: 95, 9: 123, 10: 123, 11: 180, 12: 180, 13: 180, 14: 205, 15: 215, 16: 230, 17: 66, 18: 52, 19: 65, 20: 97, 21: 150, 22: 150, 23: 245, 24: 175, 25: 66, 26: 91, 27: 113, 28: 264, 29: 175, 30: 335, 31: 109}, 'drat': {0: 3.9, 1: 3.9, 2: 3.85, 3: 3.08, 4: 3.15, 5: 2.76, 6: 3.21, 7: 3.69, 8: 3.92, 9: 3.92, 10: 3.92, 11: 3.07, 12: 3.07, 13: 3.07, 14: 2.93, 15: 3.0, 16: 3.23, 17: 4.08, 18: 4.93, 19: 4.22, 20: 3.7, 21: 2.76, 22: 3.15, 23: 3.73, 24: 3.08, 25: 4.08, 26: 4.43, 27: 3.77, 28: 4.22, 29: 3.62, 30: 3.54, 31: 4.11}, 'wt': {0: 2.62, 1: 2.875, 2: 2.32, 3: 3.215, 4: 3.44, 5: 3.46, 6: 3.57, 7: 3.19, 8: 3.15, 9: 3.44, 10: 3.44, 11: 4.07, 12: 3.73, 13: 3.78, 14: 5.25, 15: 5.424, 16: 5.345, 17: 2.2, 18: 1.615, 19: 1.835, 20: 2.465, 21: 3.52, 22: 3.435, 23: 3.84, 24: 3.845, 25: 1.935, 26: 2.14, 27: 1.513, 28: 3.17, 29: 2.77, 30: 3.57, 31: 2.78}, 'qsec': {0: 16.46, 1: 17.02, 2: 18.61, 3: 19.44, 4: 17.02, 5: 20.22, 6: 15.84, 7: 20.0, 8: 22.9, 9: 18.3, 10: 18.9, 11: 17.4, 12: 17.6, 13: 18.0, 14: 17.98, 15: 17.82, 16: 17.42, 17: 19.47, 18: 18.52, 19: 19.9, 20: 20.01, 21: 16.87, 22: 17.3, 23: 15.41, 24: 17.05, 25: 18.9, 26: 16.7, 27: 16.9, 28: 14.5, 29: 15.5, 30: 14.6, 31: 18.6}, 'vs': {0: 0, 1: 0, 2: 1, 3: 1, 4: 0, 5: 1, 6: 0, 7: 1, 8: 1, 9: 1, 10: 1, 11: 0, 12: 0, 13: 0, 14: 0, 15: 0, 16: 0, 17: 1, 18: 1, 19: 1, 20: 1, 21: 0, 22: 0, 23: 0, 24: 0, 25: 1, 26: 0, 27: 1, 28: 0, 29: 0, 30: 0, 31: 1}, 'am': {0: 1, 1: 1, 2: 1, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, 10: 0, 11: 0, 12: 0, 13: 0, 14: 0, 15: 0, 16: 0, 17: 1, 18: 1, 19: 1, 20: 0, 21: 0, 22: 0, 23: 0, 24: 0, 25: 1, 26: 1, 27: 1}}
)
As a first step, I created a density plot with a black color and that worked well.
plt.close()
plt.cla()
plt.clf()
seaborn.displot(mtcars, x="mpg", kind="kde", color = 'black', alpha=.5)
plt.suptitle("Mtcars", x=0.149, y=0.96, ha='left', fontweight = 'bold')
plt.title("density plot", loc = 'left')
plt.xlabel("mpg")
plt.ylabel("density")
plt.tight_layout()
plt.show()
Then I wanted to see if I could make that line color a fill color. So I changed color
to fill
. But this gave me weird behavior because the fill
argument seemed to work but the color was wrong.
plt.close()
plt.cla()
plt.clf()
seaborn.displot(mtcars, x="mpg", kind="kde", fill = 'black', alpha=.5)
plt.suptitle("Mtcars", x=0.125, y=0.97, ha='left', fontweight = 'bold')
plt.title("density plot", loc = 'left')
plt.xlabel("mpg")
plt.ylabel("density")
plt.tight_layout()
plt.show()
When I try both the color
and fill
arguments at the same time I get this:
plt.close()
plt.cla()
plt.clf()
seaborn.displot(mtcars, x="mpg", kind="kde", color = 'black', fill = '#ffe6b7', alpha=.5)
plt.suptitle("Mtcars", x=0.125, y=0.97, ha='left', fontweight = 'bold')
plt.title("density plot", loc = 'left')
plt.xlabel("mpg")
plt.ylabel("density")
plt.tight_layout()
plt.show()
When I looked again at the documentation for how to use seaborn at this link:
https://seaborn.pydata.org/generated/seaborn.kdeplot.html And also by typing in ?seaborn.displot
in my console, I see references to hue
instead of fill
. But hue
seems to want a vector that is a variable in the dataframe.
I tried using the hue
argument anyway and I got a blank plot.
Does anyone know how to add a line color and a fill color to a density plot that are both colors, not variables in dataframe?
plt.close()
plt.cla()
plt.clf()
seaborn.displot(mtcars, x="mpg", kind="kde", color = 'black', hue = '#ffe6b7', alpha=.5)
plt.suptitle("Mtcars", x=0.125, y=0.97, ha='left', fontweight = 'bold')
plt.title("density plot", loc = 'left')
plt.xlabel("mpg")
plt.ylabel("density")
plt.xlabel("X-Axis")
plt.ylabel("Y-Axis")
plt.tight_layout()
plt.show()
?seaborn.displot
Upvotes: 1
Views: 2094
Reputation: 80329
When no hue=
is chosen, you can set the fill color via color=
and its transparency via alpha=
. The line color can be set via ec=
(or edgecolor=
) and its thickness via lw=
(or linewidth=
).
Note that sns.displot(kind='kde', ...)
calls sns.kdeplot
under the hood. sns.displot
is the "figure-level" equivalent, creating a new figure, with one or more subplots (depending on col=
and row=
). The parameters of displot
that don't refer to the FacetGrid
are sent to kdeplot
.
import seaborn as sns
mpg = sns.load_dataset('mpg')
sns.set()
sns.displot(data=mpg['mpg'], fill=True, color='NavajoWhite', alpha=0.8, kind='kde', ec='Navy', lw=2,
height=4, aspect=3)
Upvotes: 5
Reputation: 12085
But this gave me weird behavior because the fill argument seemed to work but the color was wrong.
This is because fill
accepts a boolean. If you set it to True
, then seaborn
will fill the plot with the color defined in color
.
Although I couldn't find a proper way to achieve what you want, a quick solution is to plot it twice, once with fill
and one without. So, if you do it like this,
sns.kdeplot(data=mtcars, x='mpg', color='black')
sns.kdeplot(data=mtcars, x='mpg', alpha=.3, fill=True, color='yellow')
then you get what you want.
Upvotes: 0