add_subplot
instead of plt.subplots
is because I couldn't get plt.subplots to work for what I want to do -- which is to make nrows
and ncols
dynamic parameters so I can output charts with any shape I want: (4,1) shape, (2,2), (1,4), etc.d
(dict) to return the format string and then apply that format to the yaxis formatting but it doesn't seem to be working.import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
plt.style.use('ggplot')
df = pd.DataFrame({'Clicks': {0: 334, 1: 554, 2: 433, 3: 5353, 4: 433},
'Impressions': {0: 3242, 1: 43345, 2: 3456, 3: 34543, 4: 3453},
'Day': {0: '12/1/2015', 1: '12/2/2015', 2: '12/3/2015', 3: '12/4/2015', 4: '12/5/2015'},
'Conv': {0: 23, 1: 23, 2: 45, 3: 56, 4: 45},
'Cost': {0: 414.16, 1: 686.96, 2: 536.91, 3: 637.72, 4: 536.91}},
columns=['Day', 'Impressions', 'Clicks', 'Cost', 'Conv'])
df['Day'] = pd.to_datetime(df['Day'])
df = df.set_index('Day').resample('d', how='sum')
window = 2
nrows = 2
ncols = 2
plots = ['Impressions', 'Clicks', 'Cost', 'Conv']
d = {'Impressions':'{:,.0f}', 'Clicks': '{:,.0f}', 'Cost':'${:,.2f}', 'Conv': '{:,.0f}'}
fig = plt.figure(figsize=(8,6))
for i, plot in enumerate(plots):
ax = fig.add_subplot(nrows, ncols, i+1)
ax.plot(df.index, df[plot])
ma = pd.rolling_mean(df[plot], window)
ax.plot(df.index, ma)
mstd = pd.rolling_std(df[plot], window)
ax.fill_between(df.index, ma - 2*mstd, ma + 2*mstd, color='b', alpha=0.1)
ax.set_title(plot)
ax.get_yaxis().set_major_formatter(FuncFormatter(lambda x, p: d[plot].format(x)))
plt.tight_layout()
plt.show()
Here's the df
:
Impressions Clicks Cost Conv
Day
2015-12-01 3242 334 414.16 23
2015-12-02 43345 554 686.96 23
2015-12-03 3456 433 536.91 45
2015-12-04 34543 5353 637.72 56
2015-12-05 3453 433 536.91 45
Why is my xaxis not formatted as a date?
You need to set DateFormatter
(or similar) as major_formatter
- see code below.
How do I make all subplots share the same xaxis?
Add sharex=True
parameter to you subplots call.
You can use axes from .subplots()
if you flatten them like it is shown in the code below.
How do I apply a specific number format to each yaxis?
Your FuncFormatter
needs to return a formatted string from given tick_value
and position
like in the code below:
fig, axes = plt.subplots(2, 2, figsize=(8,6), sharex=True)
for ax, plot in zip(axes.flat, plots):
ax.plot(df.index, df[plot])
ma = pd.rolling_mean(df[plot], window)
ax.plot(df.index, ma)
mstd = pd.rolling_std(df[plot], window)
ax.fill_between(df.index, ma - 2*mstd, ma + 2*mstd, color='b', alpha=0.1)
ax.set_title(plot)
ax.yaxis.set_major_formatter(FuncFormatter(lambda x, p: '{:.0f}'.format(x)))
ax.xaxis.set_major_formatter(DateFormatter('%d-%H:%M')) # or '%d.%m.%y'
fig.autofmt_xdate() # This will rotate the xticklabels by 30 degrees so that all dates are readable.
fig.tight_layout() # no need to call this inside the loop.
This will produce a plot like this: