# Rolling/running functions with complex output on multiple variables

**URL:** <https://discourse.julialang.org/t/rolling-running-functions-with-complex-output-on-multiple-variables/95723>\
**Category:** Data\
**Created:** [March 8, 2023, 8:59am UTC](https://discourse.julialang.org/t/rolling-running-functions-with-complex-output-on-multiple-variables/95723 "2023-03-08T08:59:31Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![mreichMPI-BGC](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mreichmpi-bgc/32/43775_2.png) [@mreichMPI-BGC](https://discourse.julialang.org/u/mreichMPI-BGC)\
**Post date:** [March 8, 2023, 8:59am UTC](https://discourse.julialang.org/t/rolling-running-functions-with-complex-output-on-multiple-variables/95723/1 "2023-03-08T08:59:31Z")

</div>

Dear Julia community,

I want to run a rolling function with multiple output on multiple columns of a DataFrame. `RollingFunctions.jl` seems to allow only scalar output. `ImageFiltering.mapwindow` only allows as input a single array only.

I came up with (for a simple slope and intercept calc of a bivariate regression):

```julia
using Chain, DataFrameMacros, ImageFiltering

## Function to calc slope, intercept of y ~ x
lmBivar(x,y) = @chain lm([fill(1, length(x)) x], y) coef() (;inter=_[1], slope=_[2])

## Adapt mapwindow function to take two inputs
mapwindow2(fun, x,y, win)= mapwindow(x-> fun(getindex.(x,1), getindex.(x,2)), zip(x,y)|>collect, win)

## Apply to toy data
x = randn(1000)
y = 2x .+ 10 .+ randn(1000)

df=DataFrame(x=x,y=y)

dfs =@chain df begin 
    @transform :lmres=@bycol mapwindow2(lmBivar, :x, :y, 49)
    transform(:lmres => AsTable)
    select(Not(:lmres))
 end

```

It does what I intended, but please educate me if this ok or if there are better ways (in terms of elegance, generality, performance). Learning…

---

<div class="post-metadata">

**Author:** ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)\
**Post date:** [March 8, 2023, 6:03pm UTC](https://discourse.julialang.org/t/rolling-running-functions-with-complex-output-on-multiple-variables/95723/2 "2023-03-08T18:03:31Z")

</div>

@JeffreySarnoff is an expert on rolling functions, so maybe he can help :).

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [March 8, 2023, 7:09pm UTC](https://discourse.julialang.org/t/rolling-running-functions-with-complex-output-on-multiple-variables/95723/3 "2023-03-08T19:09:47Z")

</div>

This is a univariate regression. The parameters can be computed separately: slope is `cov(x,y)/var(x)`, the intercept is `mean(y) - b *mean(x)` (`b` is the slope). Obviously you would need to use the rolled versions of these functions.

Also,

> [@mreichMPI-BGC](#):
>
> `lm([fill(1, length(x)) x], y)`

This is going to allocate a lot of memory. Better to do (if you really want to use GLM):

```julia
@chain begin
DataFrame(x=x,y=y;copycols=false)
lm(@formula(y ~ 1 + x),df)
coef
(inter=_[1], slope=_[2]) # semi colon not needed here
end

```

---

<div class="post-metadata">

**Author:** ![mreichMPI-BGC](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mreichmpi-bgc/32/43775_2.png) [@mreichMPI-BGC](https://discourse.julialang.org/u/mreichMPI-BGC)\
**Post date:** [March 8, 2023, 7:37pm UTC](https://discourse.julialang.org/t/rolling-running-functions-with-complex-output-on-multiple-variables/95723/4 "2023-03-08T19:37:50Z")

</div>

> [@tbeason](#):
>
> This is a univariate regression. The parameters can be computed separately: slope is `cov(x,y)/var(x)`, the intercept is `mean(y) - b *mean(x)` (`b` is the slope).

Sure - it was just a MWE… For instance I want to use `quantreg` from RobustModels.jl or anything else.

> [@tbeason](#):
>
> ```julia
> @chain begin
> DataFrame(x=x,y=y;copycols=false)
> lm(@formula(y ~ 1 + x),df)
> coef
> (inter=_[1], slope=_[2]) # semi colon not needed here
> end
> 
> ```

I know this, but this is for the entire Dataframe and the point is I would not know how to get it “rolling”

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [March 8, 2023, 8:03pm UTC](https://discourse.julialang.org/t/rolling-running-functions-with-complex-output-on-multiple-variables/95723/5 "2023-03-08T20:03:07Z")

</div>

> [@mreichMPI-BGC](#):
>
> I know this, but this is for the entire Dataframe and the point is I would not know how to get it “rolling”

No, that is how you should define `lmBivar(x,y)`

---

<div class="post-metadata">

**Author:** ![mreichMPI-BGC](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mreichmpi-bgc/32/43775_2.png) [@mreichMPI-BGC](https://discourse.julialang.org/u/mreichMPI-BGC)\
**Post date:** [March 9, 2023, 9:00am UTC](https://discourse.julialang.org/t/rolling-running-functions-with-complex-output-on-multiple-variables/95723/6 "2023-03-09T09:00:10Z")

</div>

Ah thanks! Got it and makes sense!

---

<div class="post-metadata">

**Author:** ![mreichMPI-BGC](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mreichmpi-bgc/32/43775_2.png) [@mreichMPI-BGC](https://discourse.julialang.org/u/mreichMPI-BGC)\
**Post date:** [March 9, 2023, 9:55am UTC](https://discourse.julialang.org/t/rolling-running-functions-with-complex-output-on-multiple-variables/95723/7 "2023-03-09T09:55:01Z")

</div>

Thanks again - realized that `df` should of course be replaced by `_` in line 3.

FWIW my function (meanwhile I had added the function name):

```julia
regBivar(x,y, fun) = @chain begin
    DataFrame(x=x,y=y;copycols=false)
    fun(@formula(y ~ 1 + x), _)
    coef
    NamedTuple(zip(string(fun) .* ["_inter", "_slope"] .|> Symbol, _ ))
end

```
