4

I've learned about the replace function that could become my friend

dat1 <- data.frame(matrix(1:12, 3, 4))
rpl <- c(2, 4, 1)
t(sapply(seq_along(rpl), function(x) replace(dat1[x, ], rpl[x], NA)))
#      X1 X2 X3 X4
# [1,] 1  NA 7  10
# [2,] 2  5  8  NA
# [3,] NA 6  9  12

but I didn't get it to work in more complex replacement situations:

(M <- structure(c(3L, 9L, 14L, 16L, 6L, 8L, 10L, 15L, 1L, 4L, 11L, 
                 13L, 2L, 5L, 7L, 12L), .Dim = c(4L, 4L), .Dimnames = list(NULL, 
                                                                           NULL)))
#      [,1] [,2] [,3] [,4]
# [1,]    3    6    1    2
# [2,]    9    8    4    5
# [3,]   14   10   11    7
# [4,]   16   15   13   12

dat2 <- data.frame(x=matrix(NA, 16))

> sapply(1:4, function(j) replace(dat2$x, M[, j], j))
      [,1] [,2] [,3] [,4]
 [1,]   NA   NA    3   NA
 [2,]   NA   NA   NA    4
 [3,]    1   NA   NA   NA
 [4,]   NA   NA    3   NA
 [5,]   NA   NA   NA    4
 [6,]   NA    2   NA   NA
 [7,]   NA   NA   NA    4
 [8,]   NA    2   NA   NA
 [9,]    1   NA   NA   NA
[10,]   NA    2   NA   NA
[11,]   NA   NA    3   NA
[12,]   NA   NA   NA    4
[13,]   NA   NA    3   NA
[14,]    1   NA   NA   NA
[15,]   NA    2   NA   NA
[16,]    1   NA   NA   NA

The results are distributed in a matrix instead of changing just the column, whereas the for loop or the sapply give me what I want:

for (j in 1:4) dat2$x[M[, j]] <- j
# or
sapply(1:4, function(j) dat2$x[M[, j]] <<- j)

> dat3
   x
1  3
2  4
3  1
4  3
5  4
6  2
7  4
8  2
9  1
10 2
11 3
12 4
13 3
14 1
15 2
16 1

How can I properly use replace in this / such a more complex case?

BTW, why does <<- have such a bad reputation even though it fulfills its purpose, at least in this case? (Or is it just a thinking problem because I've "heard" something??). Is there an example where it's really bad practice, if it is not being used in a function that accidentally destroys something in the global environment?

jay.sf
  • 60,139
  • 8
  • 53
  • 110
  • 1
    I can't follow what you are trying to do in your second example (for instance, where does rex come from?). However, you might look into matrix indexing. In the first example, you could do `dat1[cbind(seq_len(nrow(dat1)), res)] <- NA`. There is a previous post related to your unrelated question on `<<-`. – lmo Mar 25 '19 at 14:43
  • @lmo The two small examples should only be a proxy, when I am successful and when I fail with `replace`. Do you mind link me to the related post of my unrelated `<<-` question? – jay.sf Mar 25 '19 at 14:55
  • @lmo This one? https://stackoverflow.com/q/2628621/6574038 – jay.sf Mar 25 '19 at 15:03
  • 2
    Here are three posts related to `<<-` where the answers are worth reading. [one](https://stackoverflow.com/questions/2628621/how-do-you-use-scoping-assignment-in-r), [two](https://stackoverflow.com/questions/13273002/what-does-mean-in-r), [three](https://stackoverflow.com/questions/5785290/what-is-the-difference-between-assign-and-in-r). one is the link you posted. – lmo Mar 25 '19 at 15:04

1 Answers1

1

This isn't a problem with replace. The problem is that sapply works in parallel (not in the sense of paraellel processing but just conceptually) rather than applying one iteration on the result of the prior iteration. To do that use Reduce.

transform(dat2, x = Reduce(function(x, i) replace(x, M[, i], i), init = x, 1:ncol(M)))
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341