seaborn distplot / displot与多个分布的关系

61 人关注

我正在使用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);

替换代码1】列包含3个值。0, 1, 2.

我希望看到一个萼片长度的分布图,其中target ==0target ==1target ==2,共3张图。

1 个评论
From seaborn v0.11.0 ,请看较新的答案,使用 sns.displot ,它取代了 sns.distplot
python
seaborn
histogram
density-plot
Trexion Kameha
Trexion Kameha
发布于 2017-09-05
6 个回答
Arda Arslan
Arda Arslan
发布于 2021-05-13
已采纳
0 人赞同

重要的是按照 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()

The output looks like:

如果你不知道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年),也许从那时起它已经改变了。
sns.distplot()将被弃用
Abbas
Abbas
发布于 2021-05-13
0 人赞同

对于这种类型的问题,更常见的方法是使用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并使用map来进行简单的绘制。

g = sns.FacetGrid(df, col='cols', hue="target", palette="Set1")
g = (g.map(sns.distplot, "vals", hist=False, rug=True))
    
Amit Amola
Amit Amola
发布于 2021-05-13
0 人赞同

任何试图使用新的0.11.0版本建立相同情节的人,Seaborn已经或正在废弃distplot,用dispot取代它。

So the new version wise the code would be:

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)

最后的图表看起来如下所示。

希望这对拉加夫有帮助。

是否有办法将图例的值从0、1、2改为其他值,而不改变数据框架本身的名称?
哦,这当然是可能的,让我在答案本身中回答这个问题。
@RaghavArora 查看编辑后的答案,希望这能帮助你。
toliveira
toliveira
发布于 2021-05-13
0 人赞同

我已经找到了一个更简单的解决方案,使用 面形网格 on https://github.com/mwaskom/seaborn/issues/861 by 城市人 :

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)
    
Rafael Toledo
Rafael Toledo
发布于 2021-05-13
0 人赞同

一个更近的、更简单的选择。

sns.displot(data=iris, x='sepal length (cm)', hue='target', kind='kde')
    
edge-case
edge-case
发布于 2021-05-13
0 人赞同

如果有人想得到 sns.distplot 的面网,它已经被替换成数字级的选项。 sns.displot ,以及一个轴级函数。 sns.histplot

这使得将数据从宽格式(如OP中所示)转换成长格式变得非常容易,通过使用 pandas.DataFrame.melt

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,