# [R] Apply a multi-variable function to a vector

Stephen Kennedy stevek9123 at gmail.com
Mon Sep 12 21:58:47 CEST 2016

```Hello Jeff,

I kept fooling with this, and also looking around the web and I actually
found something on stackoverflow, which does what I had in mind.  You
mentioned that you would rarely use someting like this, but the link is:

http://stackoverflow.com/questions/6192848/how-to-generalize-outer-to-n-dimensions

This may not be efficient, but what I like is that you can name the vectors
of variable values anything, as well as the names of the variables in the
arbitrary function.  It is not sensitive to the 'names' of anything.

Here is the code.  I used the function you defined for me, but for example
you can just pass in a vector of values (1:3, etc. below) and this produces
the output array.  I would name the vector something that means something
to me (temperature_vals = c(), etc.), and then pass that to multi.outer,
and the function will be applied (independent of what you name the
variables in the function).

Thanks again for your help.  The responses are like a tutorial for me ...

Best,

Steve

list_args <- Vectorize( function(a,b) c( as.list(a), as.list(b) ),
+                         SIMPLIFY = FALSE)

make_args_mtx <- function( alist ) {
+     Reduce(function(x, y) outer(x, y, list_args), alist)
+ }

multi.outer <- function(f, ... ) {
+     args <- make_args_mtx(list(...))
+     apply(args, 1:length(dim(args)), function(a) do.call(f, a[[1]] ) )
+ }

multi.outer(myfunc, 1:3, 2:6, 3:4)
, , 1

[,1] [,2] [,3] [,4] [,5]
[1,]    5    6    7    8    9
[2,]    7    9   11   13   15
[3,]    9   12   15   18   21

, , 2

[,1] [,2] [,3] [,4] [,5]
[1,]    6    7    8    9   10
[2,]    8   10   12   14   16
[3,]   10   13   16   19   22

On Sat, Sep 10, 2016 at 1:29 AM, Jeff Newmiller <jdnewmil at dcn.davis.ca.us>
wrote:

> Not sure I understand what you really want, if you have found ways to
> accomplish what you want but are not satisfied with them. That is one
> reason why keeping the mailing list involved (by reply-all) is good for
> you. From my end, I don't do one-on-one support online, and may not be able
> to carry on a thread to the end if I get busy.
>
> Your concept of a generalized outer function sounds to me like:
>
> myfunc <- function( A, B, C ) {
>  A * B + C
> }
>
> gouter <- function( FUN, ... ) {
>  args <- list( ... )
>  DF <- do.call( expand.grid, args )
>  array( data = do.call( FUN, DF )
>       , dim = sapply( args, FUN=length )
>       , dimnames = args
>       )
> }
>
> gouter( myfunc, A = 1:3, B=2:6, C=3:4 )
> # , , C = 3
> #
> #    B
> # A   2  3  4  5  6
> #   1 5  6  7  8  9
> #   2 7  9 11 13 15
> #   3 9 12 15 18 21
> #
> # , , C = 4
> #
> #    B
> # A    2  3  4  5  6
> #   1  6  7  8  9 10
> #   2  8 10 12 14 16
> #   3 10 13 16 19 22
>
> I generally just tack on columns to the expand.grid result... I almost
> never have a need for multidimensional arrays.
>
> On Fri, 9 Sep 2016, Steve Kennedy wrote:
>
> Hello,
>>
>> Abstraction is what I want.  I'm actually looking to do something more
>> complicated.  The functions do.call, and as.list get me most of the way
>> there, but there is something I'm missing ...
>>
>> My eventual goal is to produce a multi-dimensional version of 'outer'.
>> Like my.outer(func, a_vec, b_vec, c_vec, ..), where the function of the
>> variables 'a', 'b', 'c', etc. would be applied to the vectors from the
>> outer product of the vectors of values for each variable.
>>
>> I wanted to use expand.grid (does require reshaping the output).  Using
>> temps = c(40,50,60) and times = c(1:5), this doesn't quite seem to work:
>>
>>   apply(expand.grid(temps,times), 1, function(a) do.call(func2,
>> as.list(a)))
>>
>> although this does work:
>>
>>   do.call(func2, as.list(c(10, 121)))
>>
>> And, this also works:
>>
>>  apply(expand.grid(temps,times), 1, function(a) do.call("+", as.list(a)))
>>
>> There is some subtlety here I don't understand.
>>
>> Thanks,
>>
>> Steve
>>
>> -----Original Message-----
>> From: Jeff Newmiller [mailto:jdnewmil at dcn.davis.ca.us]
>> Sent: Friday, September 09, 2016 5:39 PM
>> To: Steve Kennedy; r-help at r-project.org
>> Subject: Re: [R] Apply a multi-variable function to a vector
>>
>> Your architecture has a bad smell to me. For one thing you are mixing
>> different units in the same vector but should be putting multiple instances
>> of the same variable into one vector. Lists of vectors (data frames) are
>> typically used when multiple variables need to be grouped.
>>
>> Another problem is that you are constraining the names of the variables
>> you pass to the function to be named the same as they are inside the
>> function. This really limits your use of those functions.
>>
>> There really is too much abstraction going on here.
>> --
>> Sent from my phone. Please excuse my brevity.
>>
>> On September 9, 2016 12:44:52 PM PDT, Steve Kennedy
>> <SKennedy at AnikaTherapeutics.com> wrote:
>>
>>> Hello,
>>>
>>> I would like to define an arbitrary function of an arbitrary number of
>>> variables, for example, for 2 variables:
>>>
>>> func2 <- function(time, temp) time + temp
>>>
>>> I'd like to keep variable names that have a meaning in the problem
>>> (time and temperature above).
>>>
>>> If I have a vector of values for these variables, for example in the
>>> 2-d case, c(10, 121), I'd like to apply my function (in this case
>>> func2) and obtain the result. Conceptually, something like,
>>>
>>> func2(c(10,121))
>>>
>>> becomes
>>>
>>> func2(10,121)
>>>
>>> Is there a simple way to accomplish this, for an arbitrary number of
>>> variables?  I'd like something that would simply work from the
>>> definition of the function.  If that is possible.
>>>
>>> Thanks,
>>>
>>> Steve Kennedy
>>>
>>> CONFIDENTIALITY NOTICE: This e-mail message, including
>>> a...{{dropped:11}}
>>>
>>> ______________________________________________
>>> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
>>> http://cp.mcafee.com/d/k-Kr6x0g6hASyMepov78FI6XCQXLK3AnCrFCQXLK3AnCnAPq
>>> tTT1ObPdSjqaby8VMsUyYrEl-4fgb0HoiaXcDYtmZKsHkVsTI95tCj-eHuTelGsKrpYwCOw
>>> evW_ccnpuKNRXBQQT1TfcFzCnTeEyCJtdmXP_axVZicHs3jq9JcTvANOoVcsCej76XCOsVH
>>> pFtd40wIIumd46Cy1lI-syVDoOQwvVEwtrxqsGMd44WCy3jh0p-QWNdLECZzL1
>>> http://cp.mcafee.com/d/5fHCMUp418SyMepov78FI6XCQXLK3AnCrFCQXLK3AnCnAPqt
>>> TT1ObPdSjqaby8VMsUyYrEl-4fgb0HoiaXcDYtmZKsHkVsTI95tCj-eHuTelGsKrpYwCOwe
>>> vW_ccnpuKNRXBQQT1TfcFzCnTeEyCJtdmXP_axVZicHs3jqpJcTvANOoVcsCej76XCM0gbb
>>> HhG8_qv00smHisE4iV5Ki7Y3zoyx3P2IzMkxq78qpBjHrPt3rb2qpI5-Aq83iS2PiWq811p
>>> oYIq8dd42HpYV5PeNBF0_Ph0WT2QVlwq89Rd46Cy0PZFRyrvhd_2KV
>>> and provide commented, minimal, self-contained, reproducible code.
>>>
>>
>> CONFIDENTIALITY NOTICE: This e-mail message, including any attachments,
>> contains information belonging to Anika Therapeutics, Inc. and is for the
>> sole use of the intended recipient(s) and may contain confidential,
>> proprietary, copyrighted and privileged information. Any unauthorized
>> review, use, disclosure, distribution or copying is strictly prohibited. If
>> e-mail and destroy all copies of the original message immediately.
>>
>>
> ------------------------------------------------------------
> ---------------
> Jeff Newmiller                        The     .....       .....  Go Live...
> DCN:<jdnewmil at dcn.davis.ca.us>        Basics: ##.#.       ##.#.  Live
> Go...
>                                       Live:   OO#.. Dead: OO#..  Playing
> Research Engineer (Solar/Batteries            O.O#.       #.O#.  with
> /Software/Embedded Controllers)               .OO#.       .OO#.  rocks...1k
> ------------------------------------------------------------
> ---------------
>

[[alternative HTML version deleted]]

```