如何在对数-对数 sns.regplot 中实现一条直线的回归线

3

我试图在Python中重新创建使用R创建的此绘图:

enter image description here

这是我的进展:

enter image description here

这是我所用的代码:

from matplotlib.ticker import ScalarFormatter

fig, ax = plt.subplots(figsize=(10,8))

sns.regplot(x='Platform2',y='Platform1',data=duplicates[['Platform2','Platform1']].dropna(thresh=2), scatter_kws={'s':80, 'alpha':0.5})
plt.ylabel('Platform1', labelpad=15, fontsize=15)
plt.xlabel('Platform2', labelpad=15, fontsize=15)
plt.title('Sales of the same game in different platforms', pad=30, size=20)

ax.set_xscale('log')
ax.set_yscale('log')
ax.set_xticks([1,2,5,10,20])
ax.set_yticks([1,2,5,10,20])
ax.get_xaxis().set_major_formatter(ScalarFormatter())
ax.get_yaxis().set_major_formatter(ScalarFormatter())
ax.set_xlim([0.005, 25.])
ax.set_ylim([0.005, 25.])

plt.show()

我认为我错过了一些关于对数值的概念性知识,可能是我只改变了图表的比例而未更改实际数值。当我尝试改变数值本身时,没有成功。
我想展示回归线,就像R绘图中的那条线,并同时显示x轴和y轴上的0值。但对数形式的绘图不允许我在x轴和y轴上添加0的限制。我找到了StackOverflow这个问题:LINK,但我不能使它起作用。如果有人能重新表述或有任何关于如何继续前进的建议,将会很棒!
谢谢!
1个回答

3
Seaborn的regplot可以创建一个线性空间中的线(y ~ x),或者(使用logx=True)形式为y ~ log(x)的线性回归。您的问题要求进行形式为log(y) ~ log(x)的线性回归。

这可以通过使用输入数据的log来调用regplot来实现。 然而,这将更改显示log数据轴而不是数据本身的数据轴。通过特殊的刻度格式化程序(取值的幂),这些刻度值可以再次转换为原始数据格式。

请注意,为了使其正常工作,set_xticks()set_xlim()的调用都需要将其值转换为对数空间。需要删除对set_xscale('log')的调用。

下面的代码还更改了大多数plt.调用为ax.调用,并将ax作为参数添加到sns.regplot(..., ax=ax)中。
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

sns.set()
p1 = 10 ** np.random.uniform(-2, 1, 1000)
p2 = 10 ** np.random.uniform(-2, 1, 1000)
duplicates = pd.DataFrame({'Platform1': 0.6 * p1 + 0.4 * p2, 'Platform2': 0.1 * p1 + 0.9 * p2})

fig, ax = plt.subplots(figsize=(10, 8))

data = duplicates[['Platform2', 'Platform1']].dropna(thresh=2)
sns.regplot(x=np.log10(data['Platform2']), y=np.log10(data['Platform1']),
            scatter_kws={'s': 80, 'alpha': 0.5}, ax=ax)
ax.set_ylabel('Platform1', labelpad=15, fontsize=15)
ax.set_xlabel('Platform2', labelpad=15, fontsize=15)
ax.set_title('Sales of the same game in different platforms', pad=30, size=20)

ticks = np.log10(np.array([1, 2, 5, 10, 20]))
ax.set_xticks(ticks)
ax.set_yticks(ticks)
formatter = lambda x, pos: f'{10 ** x:g}'
ax.get_xaxis().set_major_formatter(formatter)
ax.get_yaxis().set_major_formatter(formatter)
lims = np.log10(np.array([0.005, 25.]))
ax.set_xlim(lims)
ax.set_ylim(lims)

plt.show()

example plot

要创建一个类似于R中示例的jointplot(设置图形大小,请使用sns.jointplot(...., height=...),图形将始终是正方形):
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

sns.set()
p1 = 10 ** np.random.uniform(-2.1, 1.3, 1000)
p2 = 10 ** np.random.uniform(-2.1, 1.3, 1000)
duplicates = pd.DataFrame({'Platform1': 0.6 * p1 + 0.4 * p2, 'Platform2': 0.1 * p1 + 0.9 * p2})

data = duplicates[['Platform2', 'Platform1']].dropna(thresh=2)
g = sns.jointplot(x=np.log10(data['Platform2']), y=np.log10(data['Platform1']),
                  scatter_kws={'s': 80, 'alpha': 0.5}, kind='reg', height=10)

ax = g.ax_joint
ax.set_ylabel('Platform1', labelpad=15, fontsize=15)
ax.set_xlabel('Platform2', labelpad=15, fontsize=15)

g.fig.suptitle('Sales of the same game in different platforms', size=20)

ticks = np.log10(np.array([.01, .1, 1, 2, 5, 10, 20]))
ax.set_xticks(ticks)
ax.set_yticks(ticks)
formatter = lambda x, pos: f'{10 ** x:g}'
ax.get_xaxis().set_major_formatter(formatter)
ax.get_yaxis().set_major_formatter(formatter)
lims = np.log10(np.array([0.005, 25.]))
ax.set_xlim(lims)
ax.set_ylim(lims)
plt.tight_layout()
plt.show()

example of jointplot


嗨Johan,我只是想感谢你,因为你的解释不仅对我非常有效,而且我也非常清楚地理解了你的意思。所以非常感谢你抽出时间详细回答这个问题! - JourneyDS

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