Issue
I am trying to plot a bar chart and a line chart as a single plot and inclined to use seaborn
due to its nice formatting features. However, when I do df1.plot(kind='bar',...)
followed by df1.plot(kind='line',..., secondary_y=True)
, I get similar outcome as below, i.e., no line chart but no error.
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)
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'
Solution
You can build a dummy x axis and replace the values with the month data after constructing the plot:
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")
Answered By - warped
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.