0

I have 5 time series (class pandas.core.series.Series) with different frequencies and I want to make this chart: desired chart

df1 (daily data, only working days) 
Date   exchange_rate_daily
2013-01-02  25.225
2013-01-03  25.26
2013-01-04  25.35
2013-01-07  25.535
2013-01-08  25.58
2013-01-09  25.53
2013-01-10  25.63
2013-01-11  25.615
2013-01-14  25.615
2013-01-15  25.61
2013-01-16  25.58
2013-01-17  25.54
2013-01-18  25.63
2013-01-21  25.625
       
df2 (monthly data for 2 time series)
Date intervention_monthly client_monthly
2013-01-01  0.6   0.67273
2013-02-01  0.2   0.04
2013-03-01  0.4   0.17443
2013-04-01  0.3   0.53883
2013-05-01  0.7   -0.0647
2013-06-01  0.2   0.20103
2013-07-01  0.0   0.22846
2013-08-01  0.0   -0.2611
2013-09-01  0.0   0.16002
2013-10-01  0.0  -0.10967
2013-11-01  7.4  -0.31122

Line chart:

X-axis: date_exchangerate_daily (size = 2198, daily date i.e. 2013-01-02 00:00:00, but only business days - no weekends, no holidays)

Y-axis (left): `exchangerate_daily (size = 2198, daily exchange rate)

My code for this line chart works well. See below:

fig, ax1 = plt.subplots(figsize=(10,6))
ax1.plot(date_exchangerate_daily, exchangerate_daily, color="k", label="Exchange rate (daily)", linewidth=2)
ax1.legend(loc = "upper left")

Grouped bar chart:

X-axis: date_operations_monthly (size = 107, monthly date e.g. 2013-01-01 00:00:00)

Y-axis (right): intervention_monthly (size = 107, monthly data)

Y-axis (right): client_monthly (size = 107, monthly data)

x = np.arange(len(date_operations_monthly))
width = 0.1
ax2 = ax1.twinx()
rects1 = ax2.bar(x - width/2, intervention_monthly, width, label='Intervention (monthly)')
rects2 = ax2.bar(x + width/2, client_monthly, width, label='Client operation (monthly)')
ax2.set_xticks(x)
ax2.set_xticklabels(date_operations_monthly2, rotation = 70)
ax2.legend(loc = "upper right") 

And I get this chart: chart

If I plot the charts separately, I get the right charts. So there is a problem with combining these two charts. And I guess the problem is that the data frequency is different and then the size of the dates series (daily x monthly date) I want to plot on the X-axis is different. Is there please any solutions for this?

Thank you so much.

Petr_k
  • 13
  • 3
  • 1
    Welcome here! Please read this https://stackoverflow.com/questions/20109391/how-to-make-good-reproducible-pandas-examples and write a minimal reproducible example – Be Chiller Too Nov 16 '21 at 09:15

1 Answers1

0

Since there is no data available, I used the stock price data and created a bar chart using the closing price, volume, and 1/2 of the volume for the other bar chart. The matplotlib time series is based on the Gregorian calendar, so it needs to be converted. See this for more details.

import pandas as pd
import numpy as np
import io

data = '''
Date   exchange_rate_daily
2013-01-02  25.225
2013-01-03  25.26
2013-01-04  25.35
2013-01-07  25.535
2013-01-08  25.58
2013-01-09  25.53
2013-01-10  25.63
2013-01-11  25.615
2013-01-14  25.615
2013-01-15  25.61
2013-01-16  25.58
2013-01-17  25.54
2013-01-18  25.63
2013-01-21  25.625
'''

data1 = '''
Date intervention_monthly client_monthly
2013-01-01  0.6   0.67273
2013-02-01  0.2   0.04
2013-03-01  0.4   0.17443
2013-04-01  0.3   0.53883
2013-05-01  0.7   -0.0647
2013-06-01  0.2   0.20103
2013-07-01  0.0   0.22846
2013-08-01  0.0   -0.2611
2013-09-01  0.0   0.16002
2013-10-01  0.0  -0.10967
2013-11-01  7.4  -0.31122
'''
df1 = pd.read_csv(io.StringIO(data), delim_whitespace=True)
df2 = pd.read_csv(io.StringIO(data1), delim_whitespace=True)
df1['Date'] = pd.to_datetime(df1['Date'])
df2['Date'] = pd.to_datetime(df2['Date'])

import matplotlib.pyplot as plt
import matplotlib.dates as mdates

fig, ax1 = plt.subplots(figsize=(12,6))
ax1.plot(mdates.date2num(df1['Date']), df1['exchange_rate_daily'], color="k", label="Exchange rate (daily)", linewidth=2)
ax1.legend(loc = "upper left")

#x = np.arange(len(df2))
width = 0.5
ax2 = ax1.twinx()
rects1 = ax2.bar(mdates.date2num(df2['Date']) - 1, df2['intervention_monthly'], width, label='Intervention (monthly)')
rects2 = ax2.bar(mdates.date2num(df2['Date']) + 1, df2['client_monthly'], width, label='Client operation (monthly)')
all_dates = sorted(df1['Date'][::5].tolist()+df2['Date'].tolist())
all_dates = mdates.date2num(all_dates)
ax2.set_xticks(all_dates)
ax2.set_xticklabels([mdates.num2date(d).strftime('%Y-%m-%d') for d in all_dates])
ax2.legend(loc = "upper right") 
ax1.tick_params(axis='x', labelrotation=90)

plt.show()

enter image description here

r-beginners
  • 31,170
  • 3
  • 14
  • 32
  • Hello, thank you for your help. Unfortunately at this part of code: x = mdates.date2num(df.index) i got this error: AttributeError: 'numpy.int64' object has no attribute 'toordinal' – Petr_k Nov 18 '21 at 07:31
  • The code that generated this error converts the index of the data frame (date in this example) to a date format that can be handled by matplotlib. If you get an error here, it means that either the data before conversion is not in pandas date format, or it is not an index. Did this happen in all my code? Once you run it in all the codes and see how each data is converted, you will have a better understanding. Also, this question has been treated as a duplicate, but please let me know so I can help you resolve the problem. – r-beginners Nov 18 '21 at 08:20
  • Well, those similar questions don't answer my question. Your code is fine, but your loaded dataframe size is different. I am sorry, I did not show you my data sample. I will do it in next comment. – Petr_k Nov 18 '21 at 19:34
  • I added the datasample to my question – Petr_k Nov 18 '21 at 19:45
  • The data has been provided and I have updated the answers using it. The method has not been changed; the data in df1 is daily data, so the scales overlapped, so I have corrected them to 5-day intervals. – r-beginners Nov 19 '21 at 03:25
  • This is a duplicate question, but it can be accepted. – r-beginners Nov 19 '21 at 03:26
  • Thank you for your edit, but still. Even though I use pd.to_datetime, I still got AttributeError: 'numpy.datetime64' object has no attribute 'toordinal' at the part ax1.plot(mdates.date2num I got this same error also when I run your code. – Petr_k Nov 19 '21 at 08:40
  • If you get an error when you run my code, it seems to be a difference in environment. My matplotlib is the latest version of 3.4.3. What version are you using? – r-beginners Nov 19 '21 at 09:22
  • Yes :-) It was the problem. So thank you very much once again! – Petr_k Nov 19 '21 at 11:42