【问题标题】:Introducing a second y axis into a relplot() call with multiple plots在具有多个绘图的 relplot() 调用中引入第二个 y 轴
【发布时间】:2022-09-30 03:40:50
【问题描述】:

问题

我有 2 个数据框,我将它们组合起来,然后与熊猫融为一体。我需要对它们进行多重绘制(如下所示),并且代码需要可扩展。它们包括2 个变量它形成了下面的 \'key\'​​ 列(这里是 \'x\' 和 \'y\'),横跨多个\'站\'(这里只有 2 个,但需要可扩展)。我已经使用relplot() 能够在每个图表上多绘制两个变量,并在单独的图表上绘制不同的站点。

有什么方法可以保持这种格式,但在每个绘图中引入第二个 y 轴? \'x\' 和 \'y\' 需要在我的实际数据中处于不同的比例。我见过examples,其中relplot 调用与y = 1st variable 一起存储,并且为第二个变量添加了第二个lineplot 调用,其中包含ax.twinx()。所以在下面的例子中,\'x\' 和 \'y\' 在同一个图上都有一个 y 轴。

我将如何使用融化的数据框(例如下面),其中 \'key\'​​ = 2 个变量和 \'station\' 可以是长度 n?还是放弃该 df 格式并重新开始的答案?

示例代码

就目前而言的多情节:

import numpy as np
np.random.seed(123)
date_range = pd.period_range(\'1981-01-01\',\'1981-01-04\',freq=\'D\')
x = np.random.randint(1, 10, (4,2))
y = np.random.randint(1, 10, (4,2))
x = pd.DataFrame(x, index = date_range, columns = [\'station1\',\'station2\'])
y = pd.DataFrame(y, index = date_range + pd.to_timedelta(1, unit=\"D\"), columns = [\'station1\',\'station2\'])

#keep information where each data point comes from
x[\"key\"], y[\"key\"] = \"x\", \"y\"
#moving index into a column 
x = x.reset_index()
y = y.reset_index()
#and changing it to datetime values that seaborn can understand
#necessary because pd.Period data is used
x[\"index\"] = pd.to_datetime(x[\"index\"].astype(str))
y[\"index\"] = pd.to_datetime(y[\"index\"].astype(str))

#combining dataframes and reshaping 
df = pd.concat([x, y]).melt([\"index\", \"key\"], var_name=\"station\", value_name=\"station_value\")

#plotting
fg = sns.relplot(data=df, x = \"index\", y = \"station_value\", kind = \"line\", hue = \"key\", row = \"station\")

#shouldn\'t be necessary but this example had too many ticks for the interval
from matplotlib.dates import DateFormatter, DayLocator
fg.axes[0,0].xaxis.set_major_locator(DayLocator(interval=1))
fg.axes[0,0].xaxis.set_major_formatter(DateFormatter(\"%y-%m-%d\"))

plt.show()

    标签: python pandas matplotlib seaborn relplot


    【解决方案1】:

    你可以relplot 只为一个key(没有hue),然后类似于链接的线程,循环子图,创建一个twinx 和lineplot 第二个key/station 组合:

    #plotting
    fg = sns.relplot(data=df[df['key']=='x'], x="index", y="station_value", kind="line", row="station")
    
    for station, ax in fg.axes_dict.items():  
        ax1 = ax.twinx()
        sns.lineplot(data=df[(df['key'] == 'y') & (df['station'] == station)], x='index', y='station_value', color='orange', ci=None, ax=ax1)
        ax1.set_ylabel('')
    

    输出:

    【讨论】:

    • 天才。我从下面的答案中添加了facet_kws={'sharey': False, 'sharex': True},以允许 y 比例因站点而异,因为我在“key”中的“x”的真实世界数据因站点而异。在初始 relplot() 调用中添加了该参数和绘图大小参数。
    • 只是注意到删除'hue=..' 会摆脱传说。有什么办法可以重新添加吗?到目前为止,我已经尝试了很多方法,其中 best 不起作用。
    • 我假设您想要一个图例中的所有标签,例如 here?
    • 从头开始创建图例可能更容易。不确定这种替代方案的生产价值如何,但可以。将label='x' 添加到第一个relplot,并将label='y', legend=False 添加到第二个relplot。然后lines, labels = fg.fig.axes[0].get_legend_handles_labels()、lines2, labels2 = fg.fig.axes[-1].get_legend_handles_labels()、fg.fig.legend(lines+lines2, labels+labels2, loc='upper right')。
    • 哦,我只想做fg.axes[0,0].legend(lines+lines2, labels+labels2, loc='upper right') 然后 - 在轴上添加一个图例,而不是数字。
    【解决方案2】:

    不是您要求的,但是您可以在不改变 df 形状的情况下制作具有不同 y 轴的 relplots 网格

    fg = sns.relplot(
        data=df,
        x = "index",
        y = "station_value",
        kind = "line",
        col = "key",
        row = "station",
        facet_kws={'sharey': False, 'sharex': True},
    )
    

    【讨论】:

    • 仍然有帮助,我使用了facet_kws arg,可能需要像这样单独绘制变量。
    猜你喜欢
    • 2015-05-18
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 2017-01-15
    • 2016-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多