В R каждая операция является вызовом функции, включая присвоения.
Вы можете набрать ?Extract
в консоли, и вы увидите некоторую документацию для базовых операторов,
как [<-
, [[<-
и $<-
.
У объектов S4 также есть специальный оператор: slot<-
.
Поэтому, когда вы делаете что-то вроде S4obj@x <- "foo"
,
вызов функции `slot<-`(S4obj, "x", value="foo")
также может быть использован.
Это значит, что вы можете делать то, что хотите:
Map("slot<-", seurat.objects, "meta.data", value=metadata)
Однако есть одна ошибка, о которой вы должны знать.
R обычно имеет семантику копирования на изменение,
Это означает, что копия объекта создается до того, как он будет изменен.
Например:
vecs <- list(1:2, 3:4)
vecs2 <- lapply(vecs, "[<-", 1L, 0L)
> vecs
[[1]]
[1] 1 2
[[2]]
[1] 3 4
> vecs2
[[1]]
[1] 0 2
[[2]]
[1] 0 4
Это не всегда применимо,
среды и эталонные классы имеют разную семантику.
Например:
envs <- list(new.env(), new.env())
envs2 <- lapply(envs, "[[<-", "foo", "bar")
> sapply(envs, ls)
[1] "foo" "foo"
> sapply(envs2, ls)
[1] "foo" "foo"
В этом случае среды в envs
не были скопированы до изменения их для envs2
,
поэтому оба списка содержат одинаковые объекты.
По какой-то причине, , что мне интересно, если это ошибка (R v3.6.0) , которая является известной ошибкой , следующее также изменяет исходные объекты без копирования:
setClass("Foo", list(x="integer"))
s4s <- list(new("Foo", x=0L), new("Foo", x=1L))
s4s2 <- Map("slot<-", s4s, "x", value=list(2L, 3L))
> s4s
[[1]]
An object of class "Foo"
Slot "x":
[1] 2
[[2]]
An object of class "Foo"
Slot "x":
[1] 3
> s4s2
[[1]]
An object of class "Foo"
Slot "x":
[1] 2
[[2]]
An object of class "Foo"
Slot "x":
[1] 3
Так что используйте форму, предложенную akrun, если вы хотите избежать этого:
Map(function(x, y) { slot(x, "meta.data") <- y; x }, seurat.objects, metadata)