Почему присвоение ссылке (: =) дает разные результаты при запуске кода, скажем, два или три раза в формате data.table? - PullRequest
4 голосов
/ 26 мая 2020

Благодарю всех вас за ваше драгоценное время. Я хотел бы иметь таблицу с первым столбцом без лагов, вторым столбцом с одним отставанием, третьим столбцом с двумя отставаниями и т.д. c., Как на картинке. У меня есть код, который действительно выполняет эту работу, но только если вы запустите код один раз. Если вы запустите код два или три раза, вы заметите, что происходят дополнительные сдвиги (лаги). Я был бы очень благодарен, если бы кто-нибудь из вас помог мне получить тот же результат независимо от того, сколько раз запускался код.

Скриншот:

library(dplyr)
library(data.table)
d <- structure(list(inv = c(20, 18, 46, 28, 10, 17, 96, 37), c = c(1, 0.999735, 0.912009, 0.596777, 
  0.293534, 0.122216, 0.046563, 0.016929)), row.names = c(NA, -8L), class = c("tbl_df", "tbl", "data.frame"))
G <- matrix(d$inv)
W <- matrix(d$c)
K <- cbind(W%x%t(G))
dtK <- data.table(K)
z <-  dtK[, names(dtK) := Map(shift, .SD, seq_along(.SD)-1L, fill = 0), .SDcols = names(dtK)]
z

1 Ответ

3 голосов
/ 26 мая 2020

Оператор := назначает по ссылке в объекте dtK.

Это означает, что исходный объект dtK изменяется независимо от того, назначили вы его z или нет.

Попробуйте запустить только следующее и посмотрите, что произойдет:

dtK[, names(dtK) := Map(shift, .SD, seq_along(.SD)-1L, fill = 0), .SDcols = names(dtK)]
dtK
         V1        V2        V3        V4       V5       V6       V7 V8
1: 20.00000  0.000000  0.000000  0.000000  0.00000  0.00000  0.00000  0
2: 19.99470 18.000000  0.000000  0.000000  0.00000  0.00000  0.00000  0
3: 18.24018 17.995230 46.000000  0.000000  0.00000  0.00000  0.00000  0
4: 11.93554 16.416162 45.987810 28.000000  0.00000  0.00000  0.00000  0
5:  5.87068 10.741986 41.952414 27.992580 10.00000  0.00000  0.00000  0
6:  2.44432  5.283612 27.451742 25.536252  9.99735 17.00000  0.00000  0
7:  0.93126  2.199888 13.502564 16.709756  9.12009 16.99550 96.00000  0
8:  0.33858  0.838134  5.621936  8.218952  5.96777 15.50415 95.97456 37

Один из способов решения этой проблемы - сделать копию с помощью copy:

dtK <- data.table(K)
z <- copy(dtK)[, names(dtK) := Map(shift, .SD, seq_along(.SD)-1L, fill = 0), .SDcols = names(dtK)]
dtK
         V1        V2        V3        V4       V5        V6        V7        V8
1: 20.00000 18.000000 46.000000 28.000000 10.00000 17.000000 96.000000 37.000000
2: 19.99470 17.995230 45.987810 27.992580  9.99735 16.995495 95.974560 36.990195
3: 18.24018 16.416162 41.952414 25.536252  9.12009 15.504153 87.552864 33.744333
4: 11.93554 10.741986 27.451742 16.709756  5.96777 10.145209 57.290592 22.080749
5:  5.87068  5.283612 13.502564  8.218952  2.93534  4.990078 28.179264 10.860758
6:  2.44432  2.199888  5.621936  3.422048  1.22216  2.077672 11.732736  4.521992
7:  0.93126  0.838134  2.141898  1.303764  0.46563  0.791571  4.470048  1.722831
8:  0.33858  0.304722  0.778734  0.474012  0.16929  0.287793  1.625184  0.626373

Проверьте vignette("datatable-reference-semantics"), чтобы узнать больше.

...