0

Why does this not work ?

data1<-data.frame(x=1:5,y=2:6)
onevector<-c(1,2)
lapply(1:length(onevector),function(i) {data1[,i]<-data1[,i]-onevector[i]})

data1 remains unchanged...

I try to substract one element to each column of my dataset data1, I want to do :

data1[,1]<- data1[,1] -1 (which is working out of the lapply)
data1[,2]<- data1[,2] -2

My question is more about understanding the difference between lapply and for than about an alternative way to implement this, so please elaborate your answer if you want to answer.

Stéphanie C
  • 809
  • 8
  • 31
  • what are you trying to achieve, what is your expected output? – mtoto Feb 25 '16 at 10:22
  • 1
    You have to assignt the result back to `data1`: `data1[] <- lapply(1:length(min),function(i) {data1[,i]<-data1[,i]-min[i]})` – talat Feb 25 '16 at 10:24
  • the affectation should already do that, no ??? – Stéphanie C Feb 25 '16 at 10:26
  • @mtoto, it is pretty obvious but I described the 3 lines of code for you – Stéphanie C Feb 25 '16 at 10:27
  • 2
    No, the object in the global environment is not changed by the `lapply`. Btw, you could do this using `data1[] <- Map("-", data1, min)` – talat Feb 25 '16 at 10:27
  • @docendodiscimus, I am sorry this is where I get lost, if I can make an affectation in the lapply (there is no error returned), why the affectation isn't effective ? – Stéphanie C Feb 25 '16 at 10:28
  • What I don't undestand is the difference between a loop and the lapply, but I know that we should prefer apply in R rather than loops – Stéphanie C Feb 25 '16 at 10:30
  • Inside the `lapply` call you modify a _copy_ of `data1`, i.e. not the original object that is in the global environment. If you want to change the original object, you have to assign the result of the lapply call to that object in the global environment – talat Feb 25 '16 at 10:32
  • @docendodiscimus thanks for the map function I didn't know of !! – Stéphanie C Feb 25 '16 at 10:33
  • 3
    `lapply` is conceptionally different from a `for` loop. You are trying to use it like a `for` loop, which can't work. `lapply` is much more in line with functional programming, e.g., it applys a function on each element of its first parameter and changes to local objects in a function have no effect on global objects. – Roland Feb 25 '16 at 10:33
  • @Roland, thanks Roland, but in this case, shouldn't I get an error for trying to do affectation inside a lapply ? – Stéphanie C Feb 25 '16 at 10:36
  • I have no idea what you mean by "affectation". – Roland Feb 25 '16 at 10:40
  • @Roland the "<-" operation – Stéphanie C Feb 25 '16 at 10:46
  • You could have a closer look at http://adv-r.had.co.nz/Environments.html – talat Feb 25 '16 at 10:54
  • Local assignments are lost when you exit the function. `<-` actually works on a copy there. – Roland Feb 25 '16 at 10:54
  • See e.g. the example which begins with "_Let’s depict that graphically with a simpler function_" in [the link @docendo discimus suggested](http://adv-r.had.co.nz/Environments.html). – Henrik Feb 25 '16 at 10:58
  • Ok thank you for your suggestions I will have a look – Stéphanie C Feb 25 '16 at 12:52

1 Answers1

1
data1<-data.frame(x=1:5,y=2:6)
min<-c(1,2)
s <- sapply(1:length(min),function(x) rep(x,dim(data1)[1]))
data1 <- data1-s

This will create a new matrix s that is made up of columns of the values of your min vector. Subtracting this from data1 will yield your result.

Or use the solution by docendo discimus which is much more elegant:

data1 <- as.data.frame(Map("-", data1, mn))
niid
  • 473
  • 4
  • 13
  • You can avoid the `as.data.frame` call by using `data1[] <- Map("-", data1, min)`. The empty brackets `[]` will keep the structure of data1 (i.e. a data.frame) – talat Feb 25 '16 at 10:42
  • Very elegant solution indeed. – niid Feb 25 '16 at 10:43
  • Yes I do prefer the solution of @docendodiscimus, or I can do a loop, but my question was more about understanding than implementing. – Stéphanie C Feb 25 '16 at 10:49
  • My guess would be that the function inside lapply modifies a "new" data1 in local scope and does not touch the previously exsisting data1 in local scope. This question seems to be related: http://stackoverflow.com/questions/13640157/how-to-access-global-outer-scope-variable-from-r-apply-function – niid Feb 25 '16 at 10:56