使用seaborn的辅助y轴

Ger*_*rry 0 matplotlib python-3.x seaborn

我正在尝试将条形图和折线图绘制为单个图,并且seaborn由于其良好的格式功能而倾向于使用。但是,当我df1.plot(kind='bar',...)执行后df1.plot(kind='line',..., secondary_y=True),我得到如下类似的结果,即没有折线图,但没有错误。

import seaborn as sns
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Sample dataframe.
df1 = pd.DataFrame({'date':pd.date_range(datetime(2020,1,1), periods=699).tolist(), 'amount':range(1,700), 'balance':np.cumsum(range(1,700))})
df1.loc[:, 'month'] = df1['date'].dt.to_period("M")
df1.loc[:, 'month_str'] = df1['date'].dt.year.astype(str) + '-' + df1['date'].dt.month.astype(str)
df1.loc[:, 'month_dt'] = pd.to_datetime(df1.month.dt.year*10000+df1.month.dt.month*100+1,format='%Y%m%d')

# Case-1: This doesn't work.
df2 = df1.groupby(['month']).agg({'amount':'sum','balance':'sum'})
sns.barplot(x='month', y='amount', data=df2.reset_index(), palette="Blues_d")
ax2 = plt.twinx()
sns.lineplot(x='month', y='balance', data=df2.reset_index(), color='red', markers=True, ax=ax2)

# Case-2: This doesn't work (as intended, if months grow they will not auto-adjust max numbers to show and not sorted).    
df2 = df1.groupby(['month_str']).agg({'amount':'sum','balance':'sum'})
sns.barplot(x='month_str', y='amount', data=df2.reset_index(), palette="Blues_d")
ax2 = plt.twinx()
sns.lineplot(x='month_str', y='balance', data=df2.reset_index(), color='red', markers=True, ax=ax2)

# Case-3: This doesn't work either.
df2 = df1.groupby(['month_dt']).agg({'amount':'sum','balance':'sum'})
sns.barplot(x='month_dt', y='amount', data=df2.reset_index(), palette="Blues_d")
ax2 = plt.twinx()
sns.lineplot(x='month_dt', y='balance', data=df2.reset_index(), color='red', markers=True, ax=ax2)
Run Code Online (Sandbox Code Playgroud)

情况1在此输入图像描述

Traceback (most recent call last):
  File "C:\...\lib\site-packages\seaborn\_decorators.py", line 46, in inner_f
    return f(**kwargs)
  File "C:\...\lib\site-packages\seaborn\relational.py", line 703, in lineplot
    p.plot(ax, kwargs)
  File "C:\...\lib\site-packages\seaborn\relational.py", line 529, in plot
    line, = ax.plot(x, y, **kws)
  File "C:\...\lib\site-packages\matplotlib\axes\_axes.py", line 1745, in plot
    self.add_line(line)
  File "C:\...\lib\site-packages\matplotlib\axes\_base.py", line 1964, in add_line
    self._update_line_limits(line)
  File "C:\...\lib\site-packages\matplotlib\axes\_base.py", line 1986, in _update_line_limits
    path = line.get_path()
  File "C:\...\lib\site-packages\matplotlib\lines.py", line 1011, in get_path
    self.recache()
  File "C:\...\lib\site-packages\matplotlib\lines.py", line 653, in recache
    x = _to_unmasked_float_array(xconv).ravel()
  File "C:\...\lib\site-packages\matplotlib\cbook\__init__.py", line 1289, in _to_unmasked_float_array
    return np.asarray(x, float)
  File "C:\...\lib\site-packages\numpy\core\_asarray.py", line 83, in asarray
    return array(a, dtype, copy=False, order=order)
TypeError: float() argument must be a string or a number, not 'Period'
Run Code Online (Sandbox Code Playgroud)

案例2在此输入图像描述

案例3在此输入图像描述

war*_*ped 5

您可以构建一个虚拟 x 轴,并在构建绘图后用月份数据替换这些值:

fig, ax = plt.subplots()

df2 = df1.groupby(['month']).agg({'amount':'sum','balance':'sum'})

# helper axis
data = df2.reset_index()
data['xaxis'] = range(len(data))

sns.barplot(x='xaxis', y='amount', data=data, palette="Blues_d", ax=ax)
ax2 = ax.twinx()
sns.lineplot(x='xaxis', y='balance', data=data, color='red', markers=True, ax=ax2)

# replace helper axis with actual data
ax.set_xticklabels(data['month'].values, rotation = 45, ha="right")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述