使用 scipy gaussian_kde 和 seaborn kdeplot 时的 KDE 渲染差异
Diffrence KDE rendering when using scipy gaussian_kde and seaborn kdeplot
至于 documentation tell, the seaborn kdeplot work by utilizing the scipy.stats.gaussian_kde。
但是,尽管使用相同的 bandwidth
大小,但在使用 seaborn
和 gaussian_kde
绘图时,我得到了两个不同的分布。
在上图中,如果数据直接输入gaussian_kde
,左边是分布。然而,如果数据输入 seaborn kdeplot
.
,则正确的绘图是分布
此外,给定边界的曲线下面积在这两种绘制分布的方法之间并不相似。
auc using gaussian_kde : 47.7 and auc using via seaborn : 49.5
我可以知道是什么导致了这种差异吗?有没有一种方法可以使输出标准化,而不管使用什么方法(例如,seaborn
或 gaussian_kde
)
重现上述 plot
和 auc
的代码如下。
import seaborn as sns
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
time_window_order = ['272', '268', '264', '260', '256', '252', '248', '244', '240']
order_dict = {k: i for i, k in enumerate ( time_window_order )}
df = pd.DataFrame ( {'time_window': ['268', '268', '268', '264', '252', '252', '252', '240',
'256', '256', '256', '256', '252', '252', '252', '240'],
'seq_no': ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b']} )
df ['centre_point'] = df ['time_window'].map ( order_dict )
filter_band = df ["seq_no"].isin ( ['a'] )
df = df [filter_band].reset_index ( drop=True )
auc_x_min, auc_x_max = 0, 4
bandwith=0.5
########################
plt.subplots(1, 2)
# make the first plot
plt.subplot(1, 2, 1)
kde0 = gaussian_kde ( df ['centre_point'], bw_method=bandwith )
xmin, xmax = -3, 12
x_1 = np.linspace ( xmin, xmax, 500 )
kde0_x = kde0 ( x_1 )
sel_region_x = x_1 [(x_1 > auc_x_min) * (x_1 < auc_x_max)]
sel_region_y = kde0_x [(x_1 > auc_x_min) * (x_1 < auc_x_max)]
auc_bond_1 = np.trapz ( sel_region_y, sel_region_x )
area_whole = np.trapz ( kde0_x, x_1 )
plt.plot ( x_1, kde0_x, color='b', label='KDE' )
plt.ylim(bottom=0)
plt.title(f'Direct gaussian_kde with bw {bandwith}')
plt.fill_between ( sel_region_x, sel_region_y, 0, facecolor='none', edgecolor='r', hatch='xx',
label='intersection' )
# make second plot
plt.subplot(1, 2, 2)
g = sns.kdeplot ( data=df, x="centre_point", bw_adjust=bandwith )
c = g.get_lines () [0].get_data ()
x_val = c [0]
kde0_x = c [1]
idx = (x_val> auc_x_min) * (x_val < auc_x_max)
sel_region_x = x_val [idx]
sel_region_y = kde0_x [idx]
auc_bond_2 = np.trapz ( sel_region_y, sel_region_x )
g.fill_between ( sel_region_x, sel_region_y, 0, facecolor='none', edgecolor='r', hatch='xx' )
plt.title(f'Via Seaborn with bw {bandwith}')
plt.tight_layout()
plt.show()
# show much the area differ between these two plotting
print ( f'auc using gaussian_kde : {auc_bond_1 * 100:.1f} and auc using via seaborn : {auc_bond_2 * 100:.1f}' )
x=1
编辑
在的基础上,对这两行进行改动
kde0 = gaussian_kde ( df ['centre_point'], bw_method='scott' )
g = sns.kdeplot ( data=df, x="centre_point", bw_adjust=1 ) # Seaborn by default use the scott method to determine the bw size
return
从视觉上看,这两个图看起来是一样的。
但是,图表之间的auc
仍然是return两个不同的值
auc using gaussian_kde : 45.1 and auc using via seaborn : 44.6
您正在这样呼叫 scipy:
kde0 = gaussian_kde ( df ['centre_point'], bw_method=bandwith )
像这样的 seaborn
g = sns.kdeplot ( data=df, x="centre_point", bw_adjust=bandwith )
但是 kdeplot docs 告诉我们 bw_adjust
是
Factor that multiplicatively scales the value chosen using bw_method. Increasing will make the curve smoother. See Notes.
而 kdeplot 也有一个 bw_method
参数是
Method for determining the smoothing bandwidth to use; passed to scipy.stats.gaussian_kde.
因此,如果您想使两个库的结果相等,则需要确保使用了正确的参数。
至于 documentation tell, the seaborn kdeplot work by utilizing the scipy.stats.gaussian_kde。
但是,尽管使用相同的 bandwidth
大小,但在使用 seaborn
和 gaussian_kde
绘图时,我得到了两个不同的分布。
在上图中,如果数据直接输入gaussian_kde
,左边是分布。然而,如果数据输入 seaborn kdeplot
.
此外,给定边界的曲线下面积在这两种绘制分布的方法之间并不相似。
auc using gaussian_kde : 47.7 and auc using via seaborn : 49.5
我可以知道是什么导致了这种差异吗?有没有一种方法可以使输出标准化,而不管使用什么方法(例如,seaborn
或 gaussian_kde
)
重现上述 plot
和 auc
的代码如下。
import seaborn as sns
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
time_window_order = ['272', '268', '264', '260', '256', '252', '248', '244', '240']
order_dict = {k: i for i, k in enumerate ( time_window_order )}
df = pd.DataFrame ( {'time_window': ['268', '268', '268', '264', '252', '252', '252', '240',
'256', '256', '256', '256', '252', '252', '252', '240'],
'seq_no': ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b']} )
df ['centre_point'] = df ['time_window'].map ( order_dict )
filter_band = df ["seq_no"].isin ( ['a'] )
df = df [filter_band].reset_index ( drop=True )
auc_x_min, auc_x_max = 0, 4
bandwith=0.5
########################
plt.subplots(1, 2)
# make the first plot
plt.subplot(1, 2, 1)
kde0 = gaussian_kde ( df ['centre_point'], bw_method=bandwith )
xmin, xmax = -3, 12
x_1 = np.linspace ( xmin, xmax, 500 )
kde0_x = kde0 ( x_1 )
sel_region_x = x_1 [(x_1 > auc_x_min) * (x_1 < auc_x_max)]
sel_region_y = kde0_x [(x_1 > auc_x_min) * (x_1 < auc_x_max)]
auc_bond_1 = np.trapz ( sel_region_y, sel_region_x )
area_whole = np.trapz ( kde0_x, x_1 )
plt.plot ( x_1, kde0_x, color='b', label='KDE' )
plt.ylim(bottom=0)
plt.title(f'Direct gaussian_kde with bw {bandwith}')
plt.fill_between ( sel_region_x, sel_region_y, 0, facecolor='none', edgecolor='r', hatch='xx',
label='intersection' )
# make second plot
plt.subplot(1, 2, 2)
g = sns.kdeplot ( data=df, x="centre_point", bw_adjust=bandwith )
c = g.get_lines () [0].get_data ()
x_val = c [0]
kde0_x = c [1]
idx = (x_val> auc_x_min) * (x_val < auc_x_max)
sel_region_x = x_val [idx]
sel_region_y = kde0_x [idx]
auc_bond_2 = np.trapz ( sel_region_y, sel_region_x )
g.fill_between ( sel_region_x, sel_region_y, 0, facecolor='none', edgecolor='r', hatch='xx' )
plt.title(f'Via Seaborn with bw {bandwith}')
plt.tight_layout()
plt.show()
# show much the area differ between these two plotting
print ( f'auc using gaussian_kde : {auc_bond_1 * 100:.1f} and auc using via seaborn : {auc_bond_2 * 100:.1f}' )
x=1
编辑
在
kde0 = gaussian_kde ( df ['centre_point'], bw_method='scott' )
g = sns.kdeplot ( data=df, x="centre_point", bw_adjust=1 ) # Seaborn by default use the scott method to determine the bw size
return
从视觉上看,这两个图看起来是一样的。
但是,图表之间的auc
仍然是return两个不同的值
auc using gaussian_kde : 45.1 and auc using via seaborn : 44.6
您正在这样呼叫 scipy:
kde0 = gaussian_kde ( df ['centre_point'], bw_method=bandwith )
像这样的 seaborn
g = sns.kdeplot ( data=df, x="centre_point", bw_adjust=bandwith )
但是 kdeplot docs 告诉我们 bw_adjust
是
Factor that multiplicatively scales the value chosen using bw_method. Increasing will make the curve smoother. See Notes.
而 kdeplot 也有一个 bw_method
参数是
Method for determining the smoothing bandwidth to use; passed to scipy.stats.gaussian_kde.
因此,如果您想使两个库的结果相等,则需要确保使用了正确的参数。