6

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...

5 Answers 5

3

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
Sign up to request clarification or add additional context in comments.

6 Comments

I think MARGIN needs to be 2 because you want to apply v to the columns of y.
I think sweep was exactly what I was looking for. The problem is actually more complex than just adding the vector - I just used that as an example since it was the simplest thing that came to mind. What I was really looking for was a way to easily and quickly apply a multi-parameter function to each row - and that seems to be what sweep does. So thank you!
Nope, on second thought, that didn't solve my problem: sweep doesn't seem to be able to take vectors with an arbitrary number of values.
Sorry - so to clarify, I have a function that takes as parameters: vector1, vector2, vector3. Vector1 and vector2 are the same length. vector3 is of an arbitrary length. I want to apply this function to each row of my matrix. But the presence of arbitrary-length vector3 seems to be causing my code to fail. I get this error: 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
Your problem sounds more like an incorrect use of one of the functions inside your code, rather than due to unequal vector lengths. We can only guess at this point.
|
2

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

Comments

2

I don't think you need mapply here. Just use t() directly or you can use rep() to make the recycling match as you want:

> set.seed(1)
> mat <- matrix(sample(1:100, 9, TRUE), ncol = 3)
> vec <- 1:3
> 
> mat
     [,1] [,2] [,3]
[1,]   27   91   95
[2,]   38   21   67
[3,]   58   90   63
#Approach 1 using t() 
> ans1 <- t(t(mat) + vec)
#Approach 2 using rep()
> ans2 <- mat + rep(vec, each = nrow(mat))
#Are they the same?
> identical(ans1, ans2)
[1] TRUE
#Hurray!
> ans1
     [,1] [,2] [,3]
[1,]   28   93   98
[2,]   39   23   70
[3,]   59   92   66

Comments

0

How about using apply?

 t(apply(y, 1, function(x) x + v))
     [,1] [,2] [,3]
[1,]    2    8   46
[2,]    5    9    8
[3,]    1    4   35

I don't know why apply returns the row as columms so it needs to be transposed.

2 Comments

I would defintely take a look at mdply form the plyr package. This exactly does what you ask for.
I would defintely take a look at mdply form the plyr package. This exactly does what you ask for.
0

I would defintely take a look at mdply form the plyr package. This exactly does what you want to do:

mdply(data.frame(mean = 1:5, sd = 1:5), rnorm, n = 2)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.