I have a pandas dataframe df:
JavaScript
x
8
1
times = pd.date_range(start="2018-09-09",end="2020-02-02")
2
values = np.random.rand(512)
3
4
# Make df
5
df = pd.DataFrame({'Time' : times,
6
'Value': values})
7
8
And I can plot this easily using plt.plot:
But now I want to add a trendline. I tried using some answers:
How can I draw scatter trend line on matplot? Python-Pandas
Which doesn’t work:
JavaScript
1
2
1
TypeError: unsupported operand type(s) for +: 'datetime.datetime' and 'float'
2
Then I found the following question and answer:
TypeError: ufunc subtract cannot use operands with types dtype(‘<M8[ns]’) and dtype(‘float64’)
But these don’t work as well. There my understanding of the issue stops, and I can’t find anything else.
My code so far:
JavaScript
1
19
19
1
# Get values for the trend line analysis
2
x = df['Time'].dt.to_pydatetime()
3
4
# Calculate a fit line
5
trend = np.polyfit(x, df['Value'], 1)
6
fit = np.poly1d(trend)
7
8
# General plot again
9
figure(figsize=(12, 8))
10
plt.plot(x, df['Value'])
11
plt.xlabel('Date')
12
plt.ylabel('Value')
13
14
# Now trendline
15
plt.plot(x, fit(x), "r--")
16
17
# And show
18
plt.show()
19
Advertisement
Answer
One approach is to convert the dates using matplotlib’s date2num() function and its counterpart the num2date function:
JavaScript
1
34
34
1
import matplotlib.pyplot as plt
2
import pandas as pd
3
import numpy as np
4
import matplotlib.dates as dates
5
6
np.random.seed(123)
7
times = pd.date_range(start="2018-09-09",end="2020-02-02")
8
values = np.random.rand(512)
9
df = pd.DataFrame({'Time' : times,
10
'Value': values})
11
12
13
# Get values for the trend line analysis
14
x_dates = df['Time']
15
x_num = dates.date2num(x_dates)
16
17
# Calculate a fit line
18
trend = np.polyfit(x_num, df['Value'], 1)
19
fit = np.poly1d(trend)
20
21
# General plot again
22
#figure(figsize=(12, 8))
23
plt.plot(x_dates, df['Value'])
24
plt.xlabel('Date')
25
plt.ylabel('Value')
26
27
# Not really necessary to convert the values back into dates
28
#but added as a demonstration in case one wants to plot non-linear curves
29
x_fit = np.linspace(x_num.min(), x_num.max())
30
plt.plot(dates.num2date(x_fit), fit(x_fit), "r--")
31
32
# And show
33
plt.show()
34