# Differentiation without explicit function (np.gradient)

**URL:** <https://discourse.julialang.org/t/differentiation-without-explicit-function-np-gradient/57784>\
**Category:** New to Julia\
**Tags:** differentiation, gradient\
**Created:** [March 23, 2021, 1:06pm UTC](https://discourse.julialang.org/t/differentiation-without-explicit-function-np-gradient/57784 "2021-03-23T13:06:03Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Salmon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/salmon/32/22968_2.png) [@Salmon](https://discourse.julialang.org/u/Salmon)\
**Post date:** [March 23, 2021, 1:06pm UTC](https://discourse.julialang.org/t/differentiation-without-explicit-function-np-gradient/57784/1 "2021-03-23T13:06:03Z")

</div>

Hi everyone,  
I am currently looking to evaluate some numerical data and need a method similar to numpy.gradient. All the packages, I have found seem to assume that I have some continuous function that I can evaluate at arbitrary points, however I only have a fixed array of function values that I can use (i.e. x = Array{Float64,1}, y = Array{Float64,1}).  
I have found an old topic ([Is there a central difference/gradient function somewhere?](https://discourse.julialang.org/t/is-there-a-central-difference-gradient-function-somewhere/19454)) that discusses this, but I found that I was not completely satisfied with the discussed solutions and hope that something has changed since then.  
Most packages seem to have some advanced functions to differentiate matrices or higher dimensional arrays, but not simple 1-D arrays.  
The closest answer is this quick and dirty code of mine, inspired by one of the answers from above that gives what I want for evenly spaced x -Arrays:

```julia
# returns derivative of f wrt. x such that the result has a length equal to that of x
function deriv(y::AbstractVector,x::AbstractVector)
    function centraldiff(v::AbstractVector)
        dv = diff(v)/2 # half the derivative
        a = [dv[1];dv] # copies first element
        a .+= [dv;dv[end]] # copies last element, add both results to compute average
        return(a)
    end
    return centraldiff(y)./centraldiff(x)
end

```

but for such a simple problem I would not expect having to rely on my own clumsy implementation. It would be nice to import some function that can do this for non-evenly spaced x as well.  
Have I overlooked a suitable function in one of the many differentiation libraries, or is my problem ill-formulated somehow, such that there is a much better workflow altogether? Numerically, it is not feasible to compute values of y dynamically.  
I hope you can help me in this problem!

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 23, 2021, 1:27pm UTC](https://discourse.julialang.org/t/differentiation-without-explicit-function-np-gradient/57784/2 "2021-03-23T13:27:25Z")

</div>

One nice option is to use Interpolations.jl to create a piecewise linear interpolation and then ask for its derivatives:

```julia
julia> using Interpolations

julia> x = [1, 2, 4];

julia> y = [1, 2, 3];

julia> itp = interpolate((x,), y, Gridded(Linear()));

```

You can now use `itp` to interpolate values:

```julia
julia> itp(3.0)
2.5

```

and compute derivatives:

```julia
julia> Interpolations.gradient(itp, 3.0)
1-element StaticArrays.SArray{Tuple{1},Float64,1,1} with indices SOneTo(1):
 0.5

```

Note that this gives you a gradient vector, but you can get the scalar derivative by taking its only element:

```julia
julia> only(Interpolations.gradient(itp, 3.0))
0.5

```

and you can use broadcasting to get multiple derivatives at different x values:

```julia
julia> Interpolations.gradient.(Ref(itp), [1.0, 2.0, 3.0])
3-element Array{StaticArrays.SArray{Tuple{1},Float64,1,1},1}:
 [1.0]
 [1.0]
 [0.5]

```

or as scalars:

```julia
julia> only.(Interpolations.gradient.(Ref(itp), [1.0, 2.0, 3.0]))
3-element Array{Float64,1}:
 1.0
 1.0
 0.5

```

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 23, 2021, 1:30pm UTC](https://discourse.julialang.org/t/differentiation-without-explicit-function-np-gradient/57784/3 "2021-03-23T13:30:18Z")

</div>

Oh, and you can even use your interpolation as if it were a continuous-valued function (because it is), so tools like ForwardDiff also just work:

```julia
julia> using ForwardDiff

julia> ForwardDiff.derivative(itp, 3.0)
0.5

```

although it won’t be any faster than using `Interpolations.gradient`.

---

<div class="post-metadata">

**Author:** ![Salmon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/salmon/32/22968_2.png) [@Salmon](https://discourse.julialang.org/u/Salmon)\
**Post date:** [March 23, 2021, 1:49pm UTC](https://discourse.julialang.org/t/differentiation-without-explicit-function-np-gradient/57784/4 "2021-03-23T13:49:43Z")

</div>

Thank you, this is the kind of elegant solution I was looking for!

---

<div class="post-metadata">

**Author:** ![wsshin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsshin/32/360_2.png) [@wsshin](https://discourse.julialang.org/u/wsshin)\
**Post date:** [May 21, 2021, 8:40pm UTC](https://discourse.julialang.org/t/differentiation-without-explicit-function-np-gradient/57784/5 "2021-05-21T20:40:17Z")

</div>

> [@rdeits](#):
>
> you can use broadcasting to get multiple derivatives at different x values:
> 
> ```julia
> julia> Interpolations.gradient.(Ref(itp), [1.0, 2.0, 3.0])
> 3-element Array{StaticArrays.SArray{Tuple{1},Float64,1,1},1}:
> [1.0]
> [1.0]
> [0.5]
> 
> ```
> 
> or as scalars:
> 
> ```julia
> julia> only.(Interpolations.gradient.(Ref(itp), [1.0, 2.0, 3.0]))
> 3-element Array{Float64,1}:
> 1.0
> 1.0
> 0.5
> 
> ```

I think this usage of `Ref()` for evaluating the gradient at multiple points should be included in the documentation of `Interpolations.jl`. When you construct an interpolator, I think the desire to evaluate the gradient at multiple points is quite common, and yet I had no idea how to achieve it without using a for loop over the sampling points.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [May 24, 2021, 12:17pm UTC](https://discourse.julialang.org/t/differentiation-without-explicit-function-np-gradient/57784/6 "2021-05-24T12:17:09Z")

</div>

> [@wsshin](#):
>
> usage of `Ref()` for evaluating the gradient at multiple points should be included in the documentation of `Interpolations.jl` .

Note that it is not specific to that package, but a general way to escape broadcasting.

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [May 24, 2021, 12:21pm UTC](https://discourse.julialang.org/t/differentiation-without-explicit-function-np-gradient/57784/7 "2021-05-24T12:21:56Z")

</div>

Use a list comprehension like `[Interpolations.gradient(itp, x) for x in [1.0, 2.0, 3.0]]`

---

<div class="post-metadata">

**Author:** ![bozgulec](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bozgulec/32/27316_2.png) [@bozgulec](https://discourse.julialang.org/u/bozgulec)\
**Post date:** [June 12, 2021, 2:27am UTC](https://discourse.julialang.org/t/differentiation-without-explicit-function-np-gradient/57784/8 "2021-06-12T02:27:42Z")

</div>

Thank you for your answer, I was looking for the same answer for a while now! The only thing is that “only” is not defined within the Interpolations package and apparently not even within the Julia language. How can this be possible? Can it be the case that it was changed after the updates?

---

<div class="post-metadata">

**Author:** ![Salmon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/salmon/32/22968_2.png) [@Salmon](https://discourse.julialang.org/u/Salmon)\
**Post date:** [June 12, 2021, 9:14am UTC](https://discourse.julialang.org/t/differentiation-without-explicit-function-np-gradient/57784/9 "2021-06-12T09:14:46Z")

</div>

According to the docs you need at least Julia 1.4, maybe that is the issue in your case?

```julia
help?> only
search: only ReadOnlyMemoryError isreadonly download Clonglong @noinline functionloc UnionAll Culonglong @functionloc Rational

  only(x)

  Returns the one and only element of collection x, and throws an ArgumentError if the collection has zero or multiple elements.

  See also: first, last.

  │ Julia 1.4
  │
  │ This method requires at least Julia 1.4.

julia> only([1])
1

```
