matplotlibで密度プロットを作成する方法は?


122

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))

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()

matplotlibのヒストグラム

normed = Trueパラメータも試しみましたが、ガウス分布をヒストグラムに当てはめる以外の方法はありませんでした。

私の最新の試みは周りだったscipy.statsgaussian_kde、ウェブ上の例は以下のが、私はこれまで成功してきました。


回答:


124

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()

私は得る

代替テキスト

これはあなたがRから得ているものにかなり近いです。私は何をしましたか?gaussian_kde変更可能な関数を使用して、covariance_factorその帯域幅を計算します。関数を変更する前は、このデータに対してcovariance_factorによって返された値は約0.5でした。これを下げると帯域幅が下がります。_compute_covarianceすべての因子が正しく計算されるように、その関数を変更した後で呼び出す必要がありました。Rのbwパラメータと正確に対応しているわけではありませんが、うまくいけば、正しい方向に進むのに役立ちます。


6
@ジャスティンニースの答え(+1)で、Python v Rの炎上戦争などは開始したくないが、RがPythonや他の言語よりもはるかに簡潔にデータを処理する方法が好きだ。PythonにはRよりも優れた点がたくさんあると思います(私はPythonユーザーではないので、コメントできるように完全に統一されています)。データの分析よりも多くの作業に使用できますが、長期間のRとしてユーザーこのような例が出てくるまで、そのようなタスクのための言語がいかに簡潔であるかを忘れています。
Gavin Simpson

4
(まだコメントの編集と戦っています)これは、帯域幅を引数として設定できるgaussian_kdeのサブクラスであり、さらに多くの例があります:mail.scipy.org/pipermail/scipy-user/2010-January/023877.html projects.scipy.org/scipy/ticket/1092のチケット。gaussian_kdeはn次元データ用に設計されています。
ジョセフ

11
@Gavin Simpson、はい、Rはスコープが狭いため、より簡潔です。統計計算とグラフィックスのために作られています。Pythonは一般的なプログラミング言語であり、やりたいことはほとんど何でもできます。そのため、構文が簡潔ではない場合があります。その一部はNumpy / Scipyの異なるデザインですが、一部はPythonでのモジュラーセットアップです。Rは、計算とグラフィックスのみを実行する必要がある場合に最適ですが、それらの計算をいくつかのブレーダーアプリケーションで使用する必要がある場合は、Pythonのようなものが必要になる場合があります。ただし、PythonからRを使用することもできます...
Justin Peel

10
set_bandwidthメソッドとbw_methodコンストラクタの引数には、あたりのscipyのダウンロード0.11.0にgaussian_kdeに追加された問題1619
eddygeek

1
時代遅れの答え。現在Pythonで標準となっているSeabornソリューションについては、以下を参照してください。
LudvigH

148

5年後、Googleが「Pythonを使用してカーネル密度プロットを作成する方法」をGoogleにしても、このスレッドはまだトップに表示されています。

今日、これを行うはるかに簡単な方法は、多くの便利なプロット機能と優れたスタイル管理を提供するパッケージである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)

ここに画像の説明を入力してください


どうもありがとう..以来、このようなものを探していました..なぜそれbw=0.5が与えられるのかを説明できますか?
Sitz Blogz

4
@SitzBlogz bwパラメータは帯域幅を表します。OPの設定と一致させようとしました(彼の最初の最初のコード例を参照)。bwコントロールの詳細な説明については、en.wikipedia.org / wiki /…を参照してください。基本的には、密度プロットの滑らかさを制御します。帯域幅が大きいほど、滑らかになります。
Xin

私のデータが本質的に離散的であることを尋ねる別のクエリがあり、そのためにPDFをプロットしようとしていますが、scipy docを読んだ後、PMF = PDFはそれをプロットする方法に関する提案を理解していますか?
Sitz Blogz

1
私がこれを試したとき、私は得るTypeError: slice indices must be integers or None or have an __index__ method
エンドリス

48

オプション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()

ここに画像の説明を入力してください

オプション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)

ここに画像の説明を入力してください


4
帯域幅パラメータを追加する:df.plot.densityを(bw_method = 0.5)
Anake

3
@Aziz不要pandas.DataFramepandas.Series(data).plot(kind='density')@ Anake を使用可能、独立したステップとしてdf.plot.densityを設定する必要はありません。ちょうどあなたに渡すことができますbw_methodにkwargpd.Series(data).plot(kind='density', bw_method=0.5)
赤エンドウ

45

多分次のようなことを試してください:

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()

gaussian_kde()別のカーネル密度推定値で簡単に置き換えることができます。


0

密度プロットは、matplotlibを使用して作成することもできます。関数plt.hist(data)は、密度プロットに必要なy値とx値を返します(ドキュメントhttps://matplotlib.org/3.1.1/api/_as_gen/を参照)matplotlib.pyplot.hist.html)。その結果、次のコードは、matplotlibライブラリを使用して密度プロットを作成します。

import matplotlib.pyplot as plt
dat=[-1,2,1,4,-5,3,6,1,2,1,2,5,6,5,6,2,2,2]
a=plt.hist(dat,density=True)
plt.close()
plt.figure()
plt.plot(a[1][1:],a[0])      

このコードは、次の密度プロットを返します

ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.