Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I apply a multi-parameter function in R?

Tags:

r

apply

I have the following data frame and vector.

> y
  v1 v2 v3
1  1  6 43
2  4  7  5
3  0  2 32

> v
 [1] 1 2 3

I want to apply the following function to every ROW in that data frame such that v is added to every ROW of y:

x <- function(vector1,vector2) {
    x <- vector1 + vector2
}

... in order to get THESE results:

  v1 v2 v3
1  2  8 46
2  5  9  8
3  1  4 35

mapply applies the function to COLUMNS:

> z <- mapply(x, y, MoreArgs=list(vector2=v))
> z
     v1 v2 v3
[1,]  2  7 44
[2,]  6  9  7
[3,]  3  5 35

I've tried transposing the data frame so that the function will be applied to rows and not columns, but mapply gives me weird results after transposing:

> transposed <- t(y)
> transposed
   [,1] [,2] [,3]
v1    1    4    0
v2    6    7    2
v3   43    5   32

> z <- mapply(x, transposed, MoreArgs=list(vector2=v))
> z
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,]    2    7   44    5    8    6    1    3   33
[2,]    3    8   45    6    9    7    2    4   34
[3,]    4    9   46    7   10    8    3    5   35

...Help?

############################ EDIT #########################

Thanks for all the answers! I'm learning tons of new R functions that I've never seen before, which is fantastic.

I want to clarify my earlier question a bit. What I'm really asking is a much more general question - how to apply a multi-parameter function to each row in R (at the moment, I'm tempted to conclude that I should just use a loop, but I would like to figure out if it IS possible, just for future reference...) (I also purposefully refrained from showing the code I'm working with since it's kind of messy).

I tried using the sweep function as was suggested, but I get the following error:

testsweep <- function(vector, z, n) {
   testsweep <- z
}
> n <- names(Na_exp)
> n
[1] "NaCl.10000.2hr.AVG_Signal" "NaCl.10000.4hr.AVG_Signal"


> t <- head(Li_fcs,n=1)
> t
  LiCl.1000.1hr.FoldChange LiCl.2000.1hr.FoldChange LiCl.5000.1hr.FoldChange
[1,]              -0.05371838               -0.1010928              -0.01939986
     LiCl.10000.1hr.FoldChange LiCl.1000.2hr.FoldChange
[1,]                 0.1275617                -0.107154
    LiCl.2000.2hr.FoldChange LiCl.5000.2hr.FoldChange
[1,]              -0.06760782              -0.09770226
    LiCl.10000.2hr.FoldChange LiCl.1000.4hr.FoldChange
[1,]                -0.1124188              -0.06140386
    LiCl.2000.4hr.FoldChange LiCl.5000.4hr.FoldChange
[1,]              -0.04323497              -0.04275953
    LiCl.10000.4hr.FoldChange LiCl.1000.8hr.FoldChange
[1,]                0.03633496               0.01879461
    LiCl.2000.8hr.FoldChange LiCl.5000.8hr.FoldChange
[1,]                 0.257977              -0.06357423
    LiCl.10000.8hr.FoldChange
[1,]                0.07214176


> z <- colnames(Li_fcs)
> z
 [1] "LiCl.1000.1hr.FoldChange"  "LiCl.2000.1hr.FoldChange" 
 [3] "LiCl.5000.1hr.FoldChange"  "LiCl.10000.1hr.FoldChange"
 [5] "LiCl.1000.2hr.FoldChange"  "LiCl.2000.2hr.FoldChange" 
 [7] "LiCl.5000.2hr.FoldChange"  "LiCl.10000.2hr.FoldChange"
 [9] "LiCl.1000.4hr.FoldChange"  "LiCl.2000.4hr.FoldChange" 
[11] "LiCl.5000.4hr.FoldChange"  "LiCl.10000.4hr.FoldChange"
[13] "LiCl.1000.8hr.FoldChange"  "LiCl.2000.8hr.FoldChange" 
[15] "LiCl.5000.8hr.FoldChange"  "LiCl.10000.8hr.FoldChange"

But when I try to apply sweep...

> test <- sweep(t, 2, z, n, FUN="testsweep")
Error in if (check.margin) { : argument is not interpretable as logical
In addition: Warning message:
In if (check.margin) { :
  the condition has length > 1 and only the first element will be used

When I remove the n parameter from this test example, sweep works fine. This suggests to me that sweep cannot be used unless the all parameters provided to sweep are either the same number of columns as the t vector, or of length 1. Please correct me if I am mistaken...

like image 526
Christina W Avatar asked Nov 23 '11 18:11

Christina W


2 Answers

You are asking to "sweeping" v across rows of y with the "+" function:

 sweep(y, 1,  v, FUN="+")
  v1 v2 v3
1  2  7 44
2  6  9  7
3  3  5 35
like image 65
IRTFM Avatar answered Oct 02 '22 15:10

IRTFM


If your actual problem is really no more complicated than this, you can take advantage of R's recycling rules. You need to transpose y first, then add, then transpose the result because R matrices are stored in column-major order.

t(t(y)+v)
  v1 v2 v3
1  2  8 46
2  5  9  8
3  1  4 35
like image 44
Joshua Ulrich Avatar answered Oct 02 '22 15:10

Joshua Ulrich