Храните объекты S4 в data.frame или data.table - PullRequest
0 голосов
/ 28 февраля 2020

Я пытаюсь поместить сложные S4 объекты (сгенерированные с помощью пакета Seurat) в data.table (я читал, что невозможно использовать список или данные. кадр, но я не нашел ничего о совместимости data.table с объектами S4) в зависимости от значения одного их атрибута с функцией. Все эти объекты взяты из более крупного объекта, который я назвал набором данных в написанной мной функции:

 subsets_by_cluster <- function(dataset){
 nclust=data.table(cluster_ID=c(rep(NA,length(unique(dataset@active.ident)))))
 for (i in length(nclust)){
     nclust[i]=dataset[,dataset@active.ident==unique(dataset@active.ident)[i]] 
 }
 return(nclust)}

Я ожидал получить data.table, полный объектов S4 , с один столбец с таким количеством строк, как количество различных значений @ active.ident (идентификаторы кластера). Но когда я запускаю его на своем исходном наборе данных, я получаю сообщение об ошибке

Ошибка в [<-.data.frame (*tmp*, i, 1, value = new ("Seurat", assays = list (: замена имеет 2965 строк, данные имеют 1

Я также пытался сделать это вручную с такой строкой

nclust[1]=dataset[,dataset@active.ident==unique(dataset@active.ident)[1]]

, но она также не работала, вызывая ошибку:

тип 'S4' не может быть принудительно приведен в 'логический'

Сохранение подмножества в переменная работает отлично, но я бы хотел, чтобы мой скрипт мог обрабатывать разные номера кластеров . Я был думать о записи файлов для чтения, чтобы их потом можно было прочитать, но это, кажется, далеко не оптимальное решение.

есть предложения?

Ответы [ 2 ]

1 голос
/ 29 февраля 2020

Вы можете сделать это так:

library(Seurat)
library(data.table)
data(pbmc_small)

nclust = data.table(cluster_ID=levels(Idents(pbmc_small)))
nclust$data = lapply(nclust$cluster_ID,function(i){
  pbmc_small[,Idents(pbmc_small)==i]
})

И к ним можно получить доступ:

library(gridExtra)
grid.arrange(grobs=lapply(nclust$data,DimPlot),ncol=3)

enter image description here

   cluster_ID     data
1:          0 <Seurat>
2:          1 <Seurat>
3:          2 <Seurat>

ошибка в вашем коде связана с первым определением столбца как NA, и заменой их по одному за раз. И это должно быть для for(i in 1:nrow(nclust)) вместо for(i in length(nclust))

Если вы начнете с определения его как списка NA, это будет работать:

subsets_by_cluster <- function(dataset){

 lvl = levels(Idents(dataset))
 nclust=data.table(
 cluster_ID = lvl,
 data=replicate(length(lvl),NA,simplify=FALSE)
 )
 for (i in 1:nrow(nclust)){
     nclust$data[[i]]=dataset[,Idents(dataset)==lvl[i]] 
 }
 return(nclust)}

subsets_by_cluster(pbmc_small)
   cluster_ID     data
1:          0 <Seurat>
2:          1 <Seurat>
3:          2 <Seurat>
1 голос
/ 28 февраля 2020

Во-первых, создав простой класс S4 (взято из Advanced R ) Хэдли Уикхема

setClass("Person", 
  slots = c(
    name = "character",
    age = "numeric"
  )
)

Как упоминает @John Paul, вы можете создать несколько и сохранить их в списке

john <- new("Person", name = "John Smith", age = NA_real_)
jane <- new("Person", name = "Jane Smith", age = NA_integer_)

myPeeps <- list(john, jane)

Печать списка

> myPeeps
[[1]]
An object of class "Person"
Slot "name":
[1] "John Smith"

Slot "age":
[1] NA


[[2]]
An object of class "Person"
Slot "name":
[1] "Jane Smith"

Slot "age":
[1] NA

Поскольку data.frame - это особый тип list и, как мы видим выше, элемент list может быть S4 объект, вы можете хранить их в столбце. Вам просто нужно использовать функцию I()

size <- 5

propsToMyPeeps <- data.frame(
  propsFrom = I(sample(myPeeps, size, replace = TRUE)),
  propsValue = sample.int(10, size, replace = TRUE),
  propsTo = I(sample(myPeeps, size, replace = TRUE))
)

По умолчанию метод print для data.frame не знает, как привести наш Person к символьной строке, поэтому печать данных .frame приведет к ошибке. Но если вы установите под столбец, вы увидите, что все объекты там есть.

> print(propsToMyPeeps$propsTo)
[[1]]
An object of class "Person"
Slot "name":
[1] "Jane Smith"

Slot "age":
[1] NA


[[2]]
An object of class "Person"
Slot "name":
[1] "John Smith"

Slot "age":
[1] NA


[[3]]
An object of class "Person"
Slot "name":
[1] "John Smith"

Slot "age":
[1] NA


[[4]]
An object of class "Person"
Slot "name":
[1] "Jane Smith"

Slot "age":
[1] NA


[[5]]
An object of class "Person"
Slot "name":
[1] "Jane Smith"

Slot "age":
[1] NA

...