np.gradient (numpy version 1.22) returns wrong results [duplicate]

I would like to plot cos(x) and it's derivative -sin(x) on the same plot. What I do it the following:

import numpy as np    
x = np.linspace(0,10,20) #x values: 0-10, 20 values
f = np.cos(x) # function
df = np.gradient(f) # derivative

# plot
plt.plot(f, label ="function")
plt.plot(df, label ="derivative")
plt.legend()

enter image description here

Already here you can see that there is an issue with the amplitude of the derivative. It should be 1, but it's about 0.5.

If I now increase the resolution from 20 to 50 points, the amplitude of the derivative drops even more:

enter image description here

100 points:

enter image description here

1000 points:

enter image description here

Does anyone know what's going on?


It's because of the default spacing assumed between two consecutive values, which is 1. See this answer for details.

In your examples, as you're using np.linspace, spacing can be programatically found as

sp = np.diff(x)[0]

or better yet (thanks to @Kraigolas!)

# form the array *and* get the spacing in one shot
x, sp = np.linspace(0, 10, 20, retstep=True)

Then,

x, sp = np.linspace(0, 10, 2000, retstep=True)
f = np.cos(x)

df = np.gradient(f, sp) # change is here!

# plot
plt.plot(f, label ="function")
plt.plot(df, label ="derivative")
plt.legend()

gives

enter image description here

and similar for other number of points.