Извлечение и объединение фреймов данных из списка классов S4 в R

У меня есть список классов S4 (называемый vi2). Это его первая часть:

  • @ переменные: chr [1: 7]
  • @vImplist: list of 400
    • $1: Formal class '.vImp' with 2 slots
      • @Variables: chr [1:7]
      • @vImp: 'data.frame': 7 bs. of 3 variables:
        • $variables:Factor w/ 7 levels
          • $Ctest: num [1:7]
          • $ Atest: num [1: 7]
    • $2: Formal class '.vImp' with 2 slots
      • @Variables: chr [1:7]
      • @vImp: 'data.frame': 7 bs. of 3 variables:
        • $variables:Factor w/ 7 levels
          • $Ctest: num [1:7]
          • $ Atest: num [1: 7]

Всего существует 400 классов .vImp, которые имеют один и тот же формат. Я пытаюсь извлечь файл @vImp: data. frame 'для каждого класса и объединить их в новый фрейм данных. Я могу сделать это индивидуально с помощью следующей строки:

vic = as.data.frame(vi2@vImplist$'1'@vImp) 

Это создает data.frame с правильной информацией для этого класса. Однако когда я пытаюсь выполнить это для всех 400 классов одновременно, это терпит неудачу.

vic = as.data.frame(vi2@vImplist$'1:400'@vImp) 

Ошибка в as.data.frame (vi2 @ vImplist $ '1: 400' @ vImp): попытка получить слот «vImp» из объекта базового класса («NULL») без слотов.

Я также пробовал использовать цикл для выполнения задачи. Однако это также не удалось с той же ошибкой:

for (i in seq(from = 1, to = 1, by = 1)) {
vic = as.data.frame(vi2@vImplist$'[i]'@vImp)
output <- rbind(newdf,vic)
}  

Есть ли у кого-нибудь предложения по поводу того, в чем может быть проблема?


person Phil Roberts    schedule 30.05.2020    source источник


Ответы (1)


Согласно предоставленной информации, vImplist - это список из 400 записей, поэтому вы хотите получить доступ к каждой из этих записей. Записи имеют имена '1', ..., '400'. Следовательно, ваш код vic = as.data.frame(vi2@vImplist$'1'@vImp) работает. Вы ссылаетесь на запись в списке по ее имени ('1' - это символ). Когда вы используете '1:400' или '[i]', это также интерпретируется как имя из-за ''. Поскольку этих data.frames не существует, возвращается NULL, из которого производится попытка получить слот «vImp». Это объясняет ваше сообщение об ошибке.

Вам нужно перебрать все записи в списке. Самый простой способ - сделать это с помощью lapply, который работает с каждой записью в списке, и вы можете получить правильный слот:

vic <- lapply(vi2@vImplist, function(x) {
  as.data.frame(x@vImp)
})

vic теперь является списком data.frames. Если вы используете rbind с do.call, вы можете напрямую использовать список data.frames в качестве входных аргументов, поскольку do.call принимает список аргументов:

output <- do.call("rbind", vic)

Изменить

Как отметил @Rui Barradas, vImp уже является data.frame, поэтому вам не нужен as.data.frame. Кроме того, вы можете напрямую обращаться к слотам с помощью slot и использовать имя доступного слота в качестве дополнительного аргумента функции:

vic <- lapply(vi2@vImplist, slot, 'vImp') 
person starja    schedule 30.05.2020
comment
Проголосуйте за, но, учитывая структуру данных в вопросе, x@vImp уже является data.frame, lapply(vi2@vImplist, '@', 'vImp'), вероятно, это сделает. В любом случае в as.data.frame не должно быть необходимости. - person Rui Barradas; 30.05.2020
comment
@RuiBarradas хороший момент, я включил его в свой ответ. С игрушечным примером я попробовал lapply(list, '@', 'slot_name'), но у меня это не сработало, только если я напишу x@slot_name явно. - person starja; 30.05.2020
comment
Да, но lapply(list, slot, 'slot_name') работает. - person Rui Barradas; 30.05.2020