一个问题是您似乎混合了df1 和df2。你不应该只使用y='dvlnr 和df2(反之亦然)吗?
另一个问题是sns.relplot 不返回ax。相反,它返回一个FacetGrid。对于 FacetGrid,您不能调用 twinx()。您需要通过g = sns.relplot(data=df1, ...) 捕获FacetGrid 并遍历轴,在每个轴上调用twinx 并创建单独的散点图。如果数据范围足够相似,您可以合并数据框并使用hue 一次性绘制它们。
以下是一些示例代码,适用于数据范围差异太大而无法在同一 y 轴上绘制的情况:
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
df1 = pd.DataFrame({'r': np.random.randint(1, 31, 200),
'dvr': np.random.uniform(100, 1000, 200),
'Sample ID': np.random.randint(1, 5, 200)})
df2 = pd.DataFrame({'r': np.random.randint(1, 31, 300),
'dvlnr': np.random.uniform(1, 10, 300),
'Sample ID': np.random.randint(1, 5, 300)})
g = sns.relplot(data=df1, x='r', y='dvr', col='Sample ID', col_wrap=2, kind="line", height=4, aspect=1.5,
color='dodgerblue')
for sample_id, ax in g.axes_dict.items(): # axes_dict is new in seaborn 0.11.2
ax1 = ax.twinx()
sns.lineplot(data=df2[df2['Sample ID'] == sample_id], x='r', y='dvlnr', color='crimson', ax=ax1)
plt.tight_layout()
plt.show()
如果 y 数据的范围足够相似,您可以使用 hue= 合并数据框并一次性绘制所有内容。 (这种方法也适用于更多数据帧。)
- 需要添加一个新列(例如“源”)以指示原始数据框
- 两个数据框中的对应列需要相同的名称
下面是一些示例代码:
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
df1 = pd.DataFrame({'r1': np.random.randint(1, 31, 200),
'dvr1': np.random.uniform(100, 1000, 200),
'Sample ID': np.random.randint(1, 5, 200)})
df2 = pd.DataFrame({'r1': np.random.randint(1, 31, 300),
'dvlnr1': np.random.uniform(300, 1200, 300),
'Sample ID': np.random.randint(1, 5, 300)})
# add an extra column to tell to which df the data belongs
df1['source'] = 'dvr'
# the corresponding columns in both df need to have the same name for the merge
df2 = df2.rename(columns={'dvlnr1': 'dvr1'})
df2['source'] = 'dvrnr'
df_merged = pd.concat([df1, df2]).reset_index()
g = sns.relplot(data=df_merged, x='r1', y='dvr1', hue='source', col='Sample ID', col_wrap=2,
kind="line", height=4, aspect=1.5, palette='turbo')
plt.subplots_adjust(bottom=0.06, left=0.06) # plt.tight_layout() doesn't work due to legend
plt.show()