seaborn distplot / displot 具有多个分布
Posted
技术标签:
【中文标题】seaborn distplot / displot 具有多个分布【英文标题】:seaborn distplot / displot with multiple distributions 【发布时间】:2018-02-13 04:55:33 【问题描述】:我正在使用 seaborn 绘制分布图。我想用不同的颜色在同一个图上绘制多个分布:
这是我开始分布图的方式:
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
iris = load_iris()
iris = pd.DataFrame(data= np.c_[iris['data'], iris['target']],columns= iris['feature_names'] + ['target'])
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) target
0 5.1 3.5 1.4 0.2 0.0
1 4.9 3.0 1.4 0.2 0.0
2 4.7 3.2 1.3 0.2 0.0
3 4.6 3.1 1.5 0.2 0.0
4 5.0 3.6 1.4 0.2 0.0
sns.distplot(iris[['sepal length (cm)']], hist=False, rug=True);
'target'
列包含 3 个值:0、1、2。
我想查看一个萼片长度分布图,其中target ==0
、target ==1
和target ==2
,总共有 3 个图。
【问题讨论】:
来自seaborn v0.11.0
,使用sns.displot
查看更新的答案,它取代了sns.distplot
【参考方案1】:
重要的是按target
为0
、1
或2
的值对数据帧进行排序。
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
import seaborn as sns
iris = load_iris()
iris = pd.DataFrame(data=np.c_[iris['data'], iris['target']],
columns=iris['feature_names'] + ['target'])
# Sort the dataframe by target
target_0 = iris.loc[iris['target'] == 0]
target_1 = iris.loc[iris['target'] == 1]
target_2 = iris.loc[iris['target'] == 2]
sns.distplot(target_0[['sepal length (cm)']], hist=False, rug=True)
sns.distplot(target_1[['sepal length (cm)']], hist=False, rug=True)
sns.distplot(target_2[['sepal length (cm)']], hist=False, rug=True)
plt.show()
输出如下:
如果您不知道target
可能有多少个值,请在target
列中找到唯一值,然后对数据框进行切片并适当地添加到图中。
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
import seaborn as sns
iris = load_iris()
iris = pd.DataFrame(data=np.c_[iris['data'], iris['target']],
columns=iris['feature_names'] + ['target'])
unique_vals = iris['target'].unique() # [0, 1, 2]
# Sort the dataframe by target
# Use a list comprehension to create list of sliced dataframes
targets = [iris.loc[iris['target'] == val] for val in unique_vals]
# Iterate through list and plot the sliced dataframe
for target in targets:
sns.distplot(target[['sepal length (cm)']], hist=False, rug=True)
【讨论】:
这为我创建了单独的图(在 2021 年),也许它已经改变了【参考方案2】:解决此类问题的一种更常见的方法是使用 melt 将数据重新转换为长格式,然后让 map 完成剩下的工作。
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
import seaborn as sns
iris = load_iris()
iris = pd.DataFrame(data=np.c_[iris['data'], iris['target']],
columns=iris['feature_names'] + ['target'])
# recast into long format
df = iris.melt(['target'], var_name='cols', value_name='vals')
df.head()
target cols vals
0 0.0 sepal length (cm) 5.1
1 0.0 sepal length (cm) 4.9
2 0.0 sepal length (cm) 4.7
3 0.0 sepal length (cm) 4.6
4 0.0 sepal length (cm) 5.0
您现在可以简单地通过创建 FacetGrid 并使用地图进行绘图:
g = sns.FacetGrid(df, col='cols', hue="target", palette="Set1")
g = (g.map(sns.distplot, "vals", hist=False, rug=True))
【讨论】:
【参考方案3】:citynorman 在https://github.com/mwaskom/seaborn/issues/861 上使用FacetGrid 找到了一个更简单的解决方案:
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
iris = load_iris()
iris = pd.DataFrame(data= np.c_[iris['data'], iris['target']],columns= iris['feature_names'] + ['target'])
g = sns.FacetGrid(iris, hue="target")
g = g.map(sns.distplot, "sepal length (cm)", hist=False, rug=True)
【讨论】:
【参考方案4】:一个更新更简单的选项:
sns.displot(data=iris, x='sepal length (cm)', hue='target', kind='kde')
【讨论】:
【参考方案5】:任何尝试使用新的 0.11.0 版本构建相同绘图的人,Seaborn 已经或正在弃用 distplot 并将其替换为 displot。
所以新版本的代码应该是:
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
import seaborn as sns
iris = load_iris()
iris = pd.DataFrame(data=np.c_[iris['data'], iris['target']],
columns=iris['feature_names'] + ['target'])
sns.displot(data=iris, x='sepal length (cm)', hue='target', kind='kde', fill=True, palette=sns.color_palette('bright')[:3], height=5, aspect=1.5)
编辑
正如 Raghav 在评论部分所问的那样,我们能否在不更改数据框本身的情况下更改图表中的标签。是的,我们绝对可以。因此,我们首先将绘图分配给一个名为 chart
的变量,然后执行以下操作:
chart = sns.displot(data=iris, x='sepal length (cm)', hue='target', kind='kde', fill=True, palette=sns.color_palette('bright')[:3], height=5, aspect=1.5)
## Changing title
new_title = 'This is a NEW title'
chart._legend.set_title(new_title)
# Replacing labels
new_labels = ['label 1', 'label 2', 'label 3']
for t, l in zip(chart._legend.texts, new_labels):
t.set_text(l)
最终的图表如下所示:
希望这对 Raghav 有所帮助。
【讨论】:
有没有办法将图例的值从 0、1、2 更改为其他值,而无需更改数据框本身的名称 哦,这肯定是可能的,让我在答案中回答。 @RaghavArora 查看编辑后的答案,希望对您有所帮助。 太棒了,谢谢【参考方案6】:如果有人希望获得 sns.distplot
的 facetgrid,则将其替换为图形级选项 sns.displot
和轴级函数 sns.histplot
这使得使用pandas.DataFrame.melt
将数据从宽格式(如OP中所示)转换为长格式变得非常容易
import pandas as pd
import seaborn as sns
iris = sns.load_dataset('iris')
# convert the dataframe from wide to long form
iris_melt = iris.melt(id_vars='species')
iris_melt.head()
species variable value
0 setosa sepal_length 5.1
1 setosa sepal_length 4.9
2 setosa sepal_length 4.7
3 setosa sepal_length 4.6
4 setosa sepal_length 5.0
sns.displot(
data=iris_melt,
x='value',
hue='species',
kind='kde',
fill=True,
col='variable'
)
这里的图片很小,但是如果你右键点击图片并在新的标签页或窗口中打开它,你可以更好地看到细节。
【讨论】:
以上是关于seaborn distplot / displot 具有多个分布的主要内容,如果未能解决你的问题,请参考以下文章
seaborn distplot / displot 具有多个分布
在 seaborn displot/histplot 函数中绘制高斯拟合直方图(不是 distplot)