Как правильно использовать `replace` в сложных случаях? - PullRequest
4 голосов
/ 25 марта 2019

Я узнал о функции replace, которая может стать моим другом

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

но я не заставил его работать в более сложных ситуациях замены:

(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

Результаты распределяются в матрице вместо изменения только столбца, тогда как цикл for или sapply дают мне то, что я хочу:

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

Как правильно использовать replace в этом / таком более сложном случае?

Кстати, почему у <<- такая плохая репутация, хотя она и выполняет свое предназначение, по крайней мере, в этом случае? (Или это просто проблема мышления, потому что я что-то «слышал» ??). Есть ли пример, где это действительно плохая практика, если она не используется в функции, которая случайно уничтожает что-то в глобальной среде?

1 Ответ

1 голос
/ 25 марта 2019

Это не проблема с replace.Проблема заключается в том, что sapply работает параллельно (не в смысле обработки параллелей, а просто концептуально), а не применяет одну итерацию к результату предыдущей итерации.Для этого используйте Reduce.

transform(dat2, x = Reduce(function(x, i) replace(x, M[, i], i), init = x, 1:ncol(M)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...