如何在matplotlib中创建密度图?

uno*_*ode 112 python numpy r matplotlib scipy

在RI中,可以通过以下方式创建所需的输出:

data = c(rep(1.5, 7), rep(2.5, 2), rep(3.5, 8),
         rep(4.5, 3), rep(5.5, 1), rep(6.5, 8))
plot(density(data, bw=0.5))
Run Code Online (Sandbox Code Playgroud)

R中的密度图

在python(使用matplotlib)中,我得到的最接近的是一个简单的直方图:

import matplotlib.pyplot as plt
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
plt.hist(data, bins=6)
plt.show()
Run Code Online (Sandbox Code Playgroud)

matplotlib中的直方图

我也尝试了normed = True参数,但除了试图将高斯拟合到直方图之外,我无法得到任何其他参数.

我最新的尝试是围绕scipy.statsgaussian_kde,根据网站上的例子,但我一直不成功至今.

Xin*_*Xin 132

五年后,当我谷歌"如何使用python创建内核密度图"时,这个线程仍然显示在顶部!

今天,更简单的方法是使用seaborn,这个包提供了许多方便的绘图功能和良好的样式管理.

import numpy as np
import seaborn as sns
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
sns.set_style('whitegrid')
sns.kdeplot(np.array(data), bw=0.5)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • @SitzBlogz`bw`参数代表带宽.我试图匹配OP的设置(参见他原来的第一个代码示例).有关`bw`控件的详细说明,请参阅https://en.wikipedia.org/wiki/Kernel_density_estimation#Bandwidth_selection.基本上它控制着您想要密度图的平滑程度.bw越大,它就越平滑. (4认同)

Jus*_*eel 115

Sven已经展示了如何使用gaussian_kdeScipy中的类,但是你会注意到它看起来与你用R生成的类似.这是因为gaussian_kde尝试自动推断带宽.您可以使用带宽的方式改变功能发挥covariance_factor的的gaussian_kde类.首先,这是你在不改变这个功能的情况下获得的:

替代文字

但是,如果我使用以下代码:

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import gaussian_kde
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
density = gaussian_kde(data)
xs = np.linspace(0,8,200)
density.covariance_factor = lambda : .25
density._compute_covariance()
plt.plot(xs,density(xs))
plt.show()
Run Code Online (Sandbox Code Playgroud)

我明白了

替代文字

这与你从R得到的非常接近.我做了什么?gaussian_kde使用可变功能covariance_factor来计算它的带宽.在更改函数之前,covariance_factor为此数据返回的值约为.5.降低这个降低了带宽.我必须_compute_covariance在更改该功能后调用,以便正确计算所有因子.它与R的bw参数不完全一致,但希望它可以帮助您找到正确的方向.

  • @Gavin Simpson,是的,R更简洁,因为它的范围更窄.它用于统计计算和图形.Python是一种通用的编程语言,几乎可以做任何你想做的事情.因此,语法可能不那么简洁.其中一部分是Numpy/Scipy中的不同设计,但其中一部分只是Python上的模块化设置.如果您只需要进行计算和图形处理,那么R很棒,但是如果您需要在某些编程应用程序中使用这些计算,那么您可能需要像Python这样的东西.但是,您也可以使用Python中的R ... (11认同)
  • 一个`set_bandwidth`方法和一个`bw_method`构造函数参数被添加到每个[问题1619]的scipy 0.11.0中的gaussian_kde(https://github.com/scipy/scipy/issues/1619) (10认同)
  • @Justin很好的回答(+1)并且不想开始任何Python v R火焰战或任何事情,但我很喜欢R的工作方式,数据更加简洁,python和其他语言.我确信python在R上有很多优点(我不是Python用户所以我对于可能的评论非常统一)并且可以用于比分析数据更多的工作,但作为一个长期的R用户我确实忘记了这样的任务语言是多么简洁,直到这样的例子出现. (6认同)
  • (仍在编辑评论)这里是gaussian_kde的子类,允许将带宽设置为参数和更多示例:http://mail.scipy.org/pipermail/scipy-user/2010-January/023877.html和http://projects.scipy.org/scipy/ticket/1092上有一张增强票.注意,gaussian_kde是为n维数据设计的. (4认同)

Sve*_*ach 44

也许尝试类似的东西:

import matplotlib.pyplot as plt
import numpy
from scipy import stats
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
density = stats.kde.gaussian_kde(data)
x = numpy.arange(0., 8, .1)
plt.plot(x, density(x))
plt.show()
Run Code Online (Sandbox Code Playgroud)

您可以gaussian_kde()使用不同的内核密度估算轻松替换.


Azi*_*lto 42

选项1:

使用pandas数据框图(建立在上面matplotlib):

import pandas as pd
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
pd.DataFrame(data).plot(kind='density') # or pd.Series()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

选项2:

使用distplotseaborn:

import seaborn as sns
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
sns.distplot(data, hist=False)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 添加带宽参数:df.plot.density(bw_method = 0.5) (4认同)
  • @Aziz不需要`pandas.DataFrame`,可以使用`pandas.Series(data).plot(kind ='density')`@Anake,不需要将df.plot.density设置为单独的步骤;可以将您的`bw_method` kwarg传递到`pd.Series(data).plot(kind ='density',bw_method = 0.5)`中 (3认同)