如何在seaborn中使用对数刻度

35
我正在使用seaborn来绘制一些生物数据。
我想要一个基因对另一个基因的分布(在约300名患者中的表达),以下代码可以正常工作。
graph = sns.jointplot(x='Gene1', y='Gene2', data=data, kind='reg')

我喜欢图表给出了一个很好的线性拟合,以及PearsonR和P值。

One of my graphs.

然而,我想将我的数据绘制在对数刻度上,这是表示此类基因数据的常用方式。

我查看了一些在线解决方案,但它们都会删除我的PearsonR值或线性拟合,或者它们看起来不太好。例如,下面显示了一个实现。它不显示拟合线或统计信息。

Progress


你尝试过哪些解决方案并予以了拒绝? - LangeHaare
我看了这个链接:https://dev59.com/3V8e5IYBdhLWcg3wHngs 但是尝试使用那个解决方案,我的数据只得到了一条平直的线?我不确定出了什么问题,但它也没有我想要的统计信息。 - julianstanley
1
你是否尝试在调用绘图函数之前设置坐标轴,就像这里所示?https://stackoverflow.com/a/40633595/8131703 - LangeHaare
2个回答

34
mybins=np.logspace(0, np.log(100), 100)

g = sns.JointGrid(data1, data2, data, xlim=[.5, 1000000],
                  ylim=[.1, 10000000])
g.plot_marginals(sns.distplot, color='blue', bins=mybins)
g = g.plot(sns.regplot, sns.distplot)
g = g.annotate(stats.pearsonr)

ax = g.ax_joint
ax.set_xscale('log')
ax.set_yscale('log')

g.ax_marg_x.set_xscale('log')
g.ax_marg_y.set_yscale('log')

这个方法很好用。最后,我决定将表格的值转换为log(x),因为这样可以使图形更容易缩放和在短时间内可视化。


4

对于对数坐标的绘图,另一种方法是将log_scale参数传递给jointplot1的边缘组件,可以通过marginal_kws=参数完成。

import seaborn as sns
from scipy import stats
data = sns.load_dataset('tips')[['tip', 'total_bill']]**3
graph = sns.jointplot(x='tip', y='total_bill', data=data, kind='reg', marginal_kws={'log_scale': True})
#                                                                     ^^^^^^^^^^^^^ here
pearsonr, p = stats.pearsonr(data['tip'], data['total_bill'])
graph.ax_joint.annotate(f'pearsonr = {pearsonr:.2f}; p = {p:.0E}', xy=(35, 50));

result1a

如果我们不对轴进行对数缩放,我们将得到以下的图表:2 result1b

请注意,相关系数是相同的,因为用于导出两条拟合线的基础回归函数是相同的。


尽管上面第一个图中的拟合线看起来不是线性的,但它确实是线性的,只是轴被对数缩放了,这“扭曲”了视图。在底层,sns.jointplot() 调用 sns.regplot() 来绘制散点图和拟合线,因此如果我们使用相同的数据并对数缩放轴调用它,我们将得到相同的图。换句话说,以下代码将产生相同的散点图。

sns.regplot(x='tip', y='total_bill', data=data).set(xscale='log', yscale='log');

如果在将数据传递给jointplot()之前对其进行对数处理,那么这将是完全不同的模型(您可能不想要它),因为现在回归系数将来自于log(y)=a+b*log(x)而不是之前的y=a+b*x
您可以在下面的图中看到差异。即使拟合线现在看起来是线性的,相关系数也已经改变了。

result2


1 边际图使用 sns.histplot 绘制,该函数支持 log_scale 参数。

2 一个方便的函数用于绘制本文中的图形:

from scipy import stats
def plot_jointplot(x, y, data, xy=(0.4, 0.1), marginal_kws=None, figsize=(6,4)):
    # compute pearsonr
    pearsonr, p = stats.pearsonr(data[x], data[y])
    # plot joint plot
    graph = sns.jointplot(x=x, y=y, data=data, kind='reg', marginal_kws=marginal_kws)
    # annotate the pearson r results
    graph.ax_joint.annotate(f'pearsonr = {pearsonr:.2f}; p = {p:.0E}', xy=xy);
    # set figsize
    graph.figure.set_size_inches(figsize);
    return graph

data = sns.load_dataset('tips')[['tip', 'total_bill']]**3
plot_jointplot('tip', 'total_bill', data, (50, 35), {'log_scale': True})  # log-scaled
plot_jointplot('tip', 'total_bill', data, (550, 3.5))                     # linear-scaled
plot_jointplot('tip', 'total_bill', np.log(data), (3.5, 3.5))             # linear-scaled on log data

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接