Используйте ссылочный класс в качестве уровней фактора

У кого-нибудь есть опыт использования ссылочных классов в качестве уровней фактора? Это один из моих шагов по добавлению поддержки, подобной внешнему ключу, к data.frame в одном из моих пакетов.

Я в конечном итоге хочу создать data.frame которые могут хранить в виде целых чисел коды, связанные с фактором, но уровни этого фактора на самом деле являются объектами эталонного класса, а не факторами векторов символов, которые обычно используются. Мне удалось найти некоторую информацию об использовании объектов S4 в качестве уровней фактора, но методы, похоже, не работают для эталонных классов.

Например, простое:

> myClass <- setRefClass("MyClass", fields=list(a="numeric", b="character"))
> myObj <- myClass$new(a=1, b="test")
> factor(myObj)
Error in unique.default(x) : unique() applies only to vectors
> as.character(myObj)
Error in as.vector(x, "character") : 
  cannot coerce type 'environment' to vector of type 'character'
> as.character.MyClass <- function(x){ x$b }
> as.character(myObj)
[1] "test"
> factor(myObj)
Error in unique.default(x) : unique() applies only to vectors
>
> unique.MyClass <- function (x, incomparables = FALSE, ...) { unique(as.character(x)) }
> factor(myObj)
Error in as.vector(x, mode) : invalid 'mode' argument
> traceback()
2: as.vector(exclude, typeof(x))
1: factor(myObj)

похоже, ничего не работает. Похоже, в лучшем случае, я могу добраться до линии в factor() который анализирует exclude параметр:

exclude <- as.vector(exclude, typeof(x))

в этот момент все разваливается, так как мне не разрешено создавать вектор типа "S4".

Любые мысли о том, как решить этот или, что еще лучше, альтернативные подходы для отображения целого числа в объекте Reference Class в data.frame-дружественный способ будет высоко ценится!


Изменить: В ответ на вопрос @ Аарона ниже:

Простым решением здесь будет просто хранить целые числа в data.frame а затем вести отдельный список /data.frame отвечает за сопоставление этих идентификаторов с некоторыми другими данными (такими как объекты ссылочного класса). Это позволит сохранить все необходимые данные для выполнения того, что мне нужно, но для меня будет менее изящным по нескольким причинам:

  1. Я предполагаю решение, которое позволило бы мне распечатать некоторую часть объекта Reference Class, а не ID. Например, если я сопоставляю идентификаторы сотрудников (целое число) с классом "Сотрудник", мне бы хотелось, чтобы мои data.frame печатать имена сотрудников, а не их удостоверения личности.
  2. Я хотел бы иметь возможность извлекать объекты непосредственно из data.frame, Точно так же, как as.character(myDataFrame$someColumn) даст мне метки этого столбца (при условии, что это фактор), а не базовые целые числа, которые на самом деле хранятся в data.frame,

Опять же, я очень открыт для альтернативных решений этой проблемы, если есть лучший способ сделать это!

1 ответ

Я думаю, что это можно сделать, сделав новый класс, скажем, myFactorс необходимыми методами; format кажется, что вам нужно для печати во фрейме данных; Вы могли бы легко добавить print или другие методы по вашему выбору. Мне удобнее всего использовать методы S3, вот что я здесь сделал.

Здесь я настроил ваш справочный класс и format функция для myFactor учебный класс.

myClass <- setRefClass("MyClass", fields=list(a="numeric", b="character"))
format.myFactor <- function(obj, ...) {
  n <- sapply(levels(obj), function(x) x[["b"]])
  n[obj]
}

Здесь я создаю два новых эталонных объекта и использую их как уровни моего нового myFactor объект.

myObj <- myClass$new(a=1, b="test")
myObj2 <- myClass$new(a=4, b="testagain")
foo <- structure(c(2,1,2), levels=c(myObj, myObj2), class=c("myFactor","numeric"))
d <- data.frame(x=foo)

Затем он печатает красиво.

> d
          x
1 testagain
2      test
3 testagain
Другие вопросы по тегам