# Linear interpolation in 4D?

**URL:** https://discourse.julialang.org/t/linear-interpolation-in-4d/65276
**Category:** New to Julia
**Tags:** question, interpolations
**Created:** [July 25, 2021, 7:50pm UTC](https://discourse.julialang.org/t/linear-interpolation-in-4d/65276 "2021-07-25T19:50:11Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![marianoarnaiz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marianoarnaiz/32/19377_2.png) [@marianoarnaiz](https://discourse.julialang.org/u/marianoarnaiz)
#### Post date: [July 25, 2021, 7:50pm UTC](https://discourse.julialang.org/t/linear-interpolation-in-4d/65276/1 "2021-07-25T19:50:11Z")

</div>

Hi Forum!  
Yes, another question on interpolation.  
I have this 5D data that I need linearly interpolated (spline and quadratic are good, but I need to avoid any overshoot). If anyone os curios the data is something like this:

[https://github.com/marianoarnaiz/SWF/blob/main/Felsic.txt](https://github.com/marianoarnaiz/SWF/blob/main/Felsic.txt)

Now, columns 1 and 2 are OK, but 3:5 are peculiar they must add to 100%. Column 6 is what needs to be interpolated (actually 6:8 will all be interpolated in different variables).

I tried using Interpolations like this:

> DATA\_FELSIC=readdlm(“Felsic.txt”,Float64,comments=true,comment\_char=‘#’); #This is the IASP91 with LAB  
> DATA\_FELSIC[:,2]=DATA\_FELSIC[:,2]\*1e-9;  
> Temperature=DATA\_FELSIC[:,1]; #in K  
> Pressure=DATA\_FELSIC[:,2]; #in Gpa  
> Qz=DATA\_FELSIC[:,3]; #in %  
> A=DATA\_FELSIC[:,4]; #in %  
> P=DATA\_FELSIC[:,5];#in %  
> Vp=DATA\_FELSIC[:,6]; #in km/s  
> Vs=DATA\_FELSIC[:,7]; #in km/s  
> Rho=DATA\_FELSIC[:,8]; #in g/cm3
> 
> t=sort(unique(Temperature));  
> pr=sort(unique(Pressure));  
> q=sort(unique(Qz));  
> a=sort(unique(A));  
> pl=sort(unique(P));
> 
> Felsic\_Rho\_M=zeros(size(t,1),size(pr,1),size(q,1),size(a,1),size(pl,1));
> 
> for ti=1:size(t,1)  
> for pri=1:size(pr,1)  
> for qi=1:size(q,1)  
> for ai=1:size(a,1)  
> for pli=1:size(pl,1)  
> if q[qi]+a[ai]+pl[pli]==100  
> indx=findall( (DATA\_FELSIC[:,1].==t[ti]) .& (DATA\_FELSIC[:,2].==pr[pri]) .& (DATA\_FELSIC[:,3].==q[qi]) .& (DATA\_FELSIC[:,4].==a[ai]) .& (DATA\_FELSIC[:,5].==pl[pli]));  
> Felsic\_Rho\_M[ti,pri,qi,ai,pli]=Rho[indx[1]];
> 
> ```
> end
> end
> end
> end
> end
> 
> ```
> 
> end
> 
> Felsic\_Rho = interpolate((t,pr,q,a,pl), Felsic\_Rho\_M, Gridded(Linear()));

But to fill Matrix I have used zeros and this makes my interpolation have all minimum values outside the knots.

Any way around this? Thanks!

---

<div class="post-metadata">

### Author: ![maxfreu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxfreu/32/17468_2.png) [@maxfreu](https://discourse.julialang.org/u/maxfreu)
#### Post date: [July 25, 2021, 8:40pm UTC](https://discourse.julialang.org/t/linear-interpolation-in-4d/65276/2 "2021-07-25T20:40:48Z")

</div>

Maybe you can use ‘upsample\_trilinear‘ in NNlib for this. It upsamples the first three dims of a 5D array. Sorry, I‘m on the phone and cant give a proper example.

---

<div class="post-metadata">

### Author: ![blackeneth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/blackeneth/32/10353_2.png) [@blackeneth](https://discourse.julialang.org/u/blackeneth)
#### Post date: [July 26, 2021, 4:21am UTC](https://discourse.julialang.org/t/linear-interpolation-in-4d/65276/3 "2021-07-26T04:21:39Z")

</div>

It looks like you’re trying to delete duplicate data in the `Felsic.txt` source data.

It appears you reduce each variable to a unique value, then do a nested loop to look up each dependent variable to re-create the matrix.

Here is an easier way:

```julia
using CSV
using DataFrames 
df = CSV.File("C:\\Users\\<user>\\Documents\\JuliaCode\\Felsic.txt",header=0) |> DataFrame #This is the IASP91 with LAB
data_felsic=Matrix{Float64}(unique!(df))

```

In this case, your data doesn’t have any duplicate rows.

_One style note:_ don’t end Julia lines with “;” – not needed and not recommended.

In addition, _good news,_ your data is _4D_, not 5D. Columns 3,4,5 (Qz,A,P) are a _composition_ or _mixture_ that adds up to 100%. So if you know 2 of the values, the third is known by subtracting those two from 100%. For example, Qz = 100 - A - P. In short, your have [multicollinearity](https://en.wikipedia.org/wiki/Multicollinearity) in your dataset. You only need to include any 2 of the 3 variables in your model.

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [July 26, 2021, 8:14am UTC](https://discourse.julialang.org/t/linear-interpolation-in-4d/65276/4 "2021-07-26T08:14:08Z")

</div>

More of a question than an answer: could this be a use case for [NearestNeighbors.jl](https://github.com/KristofferC/NearestNeighbors.jl)?

Say, one would get k-neighbors first and then use inverse distance weighting (or other) to compute the interpolated value.

---

<div class="post-metadata">

### Author: ![marianoarnaiz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marianoarnaiz/32/19377_2.png) [@marianoarnaiz](https://discourse.julialang.org/u/marianoarnaiz)
#### Post date: [July 26, 2021, 8:33am UTC](https://discourse.julialang.org/t/linear-interpolation-in-4d/65276/5 "2021-07-26T08:33:13Z")

</div>

I can give that a try

---

<div class="post-metadata">

### Author: ![marianoarnaiz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marianoarnaiz/32/19377_2.png) [@marianoarnaiz](https://discourse.julialang.org/u/marianoarnaiz)
#### Post date: [July 26, 2021, 8:34am UTC](https://discourse.julialang.org/t/linear-interpolation-in-4d/65276/6 "2021-07-26T08:34:33Z")

</div>

Well, the repeated values are no problem. I do not think there are any. My problem is how to turn that into a interpolated function.

---

<div class="post-metadata">

### Author: ![marianoarnaiz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marianoarnaiz/32/19377_2.png) [@marianoarnaiz](https://discourse.julialang.org/u/marianoarnaiz)
#### Post date: [July 26, 2021, 8:35am UTC](https://discourse.julialang.org/t/linear-interpolation-in-4d/65276/7 "2021-07-26T08:35:09Z")

</div>

> [@rafael.guerra](#):
>
> NearestNeighbors.jl

I will give that a try too! Thanks Rafael!

---

<div class="post-metadata">

### Author: ![RJDennis](https://avatars.discourse-cdn.com/v4/letter/r/90db22/32.png) [@RJDennis](https://discourse.julialang.org/u/RJDennis)
#### Post date: [July 26, 2021, 1:58pm UTC](https://discourse.julialang.org/t/linear-interpolation-in-4d/65276/8 "2021-07-26T13:58:09Z")

</div>

Will this package do what you want?

[https://github.com/RJDennis/PiecewiseLinearApprox.jl](https://github.com/RJDennis/PiecewiseLinearApprox.jl)

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [July 26, 2021, 3:10pm UTC](https://discourse.julialang.org/t/linear-interpolation-in-4d/65276/9 "2021-07-26T15:10:10Z")

</div>

@RJDennis, thanks for the package link.

Could you please confirm, say for the 4d case with variables `x1,x2,x3,x4`, that we will need to define a range for each one (nodes / hypercube grid) and that the dependent variable `y` to interpolate at a point `(x1ₒ,x2ₒ,x3ₒ,x4ₒ)` needs to be defined everywhere over the hypercube grid?

---

<div class="post-metadata">

### Author: ![marianoarnaiz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marianoarnaiz/32/19377_2.png) [@marianoarnaiz](https://discourse.julialang.org/u/marianoarnaiz)
#### Post date: [July 26, 2021, 4:33pm UTC](https://discourse.julialang.org/t/linear-interpolation-in-4d/65276/10 "2021-07-26T16:33:20Z")

</div>

Sounds like it could work. Can you give an example of how it works?

---

<div class="post-metadata">

### Author: ![marianoarnaiz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marianoarnaiz/32/19377_2.png) [@marianoarnaiz](https://discourse.julialang.org/u/marianoarnaiz)
#### Post date: [July 26, 2021, 4:37pm UTC](https://discourse.julialang.org/t/linear-interpolation-in-4d/65276/11 "2021-07-26T16:37:47Z")

</div>

Just an update…  
I tried [ScatteredInterpolation.jl](https://github.com/eljungsk/ScatteredInterpolation.jl) with some success but it overshoots in some positions.  
Any idea if there is a similar package that includes linear interpolation. This one doesn’t.  
Thanks for the help!

---

<div class="post-metadata">

### Author: ![RJDennis](https://avatars.discourse-cdn.com/v4/letter/r/90db22/32.png) [@RJDennis](https://discourse.julialang.org/u/RJDennis)
#### Post date: [July 26, 2021, 5:41pm UTC](https://discourse.julialang.org/t/linear-interpolation-in-4d/65276/12 "2021-07-26T17:41:40Z")

</div>

I think rafael.guerra is right in that the package wont help you because it requires y to be defined at each point on a hypergrid.

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [July 26, 2021, 10:19pm UTC](https://discourse.julialang.org/t/linear-interpolation-in-4d/65276/13 "2021-07-26T22:19:08Z")

</div>

@marianoarnaiz, thanks for highlighting the very interesting ScatteredInterpolation.jl package.

The results from its Shepard interpolation method look good to me:

```julia
using ScatteredInterpolation, CSV, DataFrames

df = CSV.File(filename; header=false) |> DataFrame

rename!(df,["T", "Pr", "Qz", "A", "P", "Vp", "Vs", "Rho"])

# Qz + A + P = 100 => variables domain is 4d
# interpolate Vp (Vs and Rhob) function of T, Pr, Qz and A

points = permutedims(Matrix(df[:,1:4]))

itp_Vp = interpolate(Shepard(), points, df[:,"Vp"]);
itp_Vs = interpolate(Shepard(), points, df[:,"Vs"]);
itp_Rho = interpolate(Shepard(), points, df[:,"Rho"]);

xₒ = [1000; 2e9; 50; 30] # "T", "Pr", "Qz", "A"

Vpₒ = evaluate(itp_Vp, xₒ) # 6.8336 km/s
Vsₒ = evaluate(itp_Vs, xₒ) # 4.0778 km/s
Rhoₒ = evaluate(itp_Rho, xₒ) # 2.7836 g/cc

```

---

<div class="post-metadata">

### Author: ![marianoarnaiz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marianoarnaiz/32/19377_2.png) [@marianoarnaiz](https://discourse.julialang.org/u/marianoarnaiz)
#### Post date: [July 27, 2021, 5:52pm UTC](https://discourse.julialang.org/t/linear-interpolation-in-4d/65276/14 "2021-07-27T17:52:01Z")

</div>

It is not perfect. But it is the closet solution to the problem!
