Используйте ссылочный класс в качестве уровней фактора
У кого-нибудь есть опыт использования ссылочных классов в качестве уровней фактора? Это один из моих шагов по добавлению поддержки, подобной внешнему ключу, к 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
отвечает за сопоставление этих идентификаторов с некоторыми другими данными (такими как объекты ссылочного класса). Это позволит сохранить все необходимые данные для выполнения того, что мне нужно, но для меня будет менее изящным по нескольким причинам:
- Я предполагаю решение, которое позволило бы мне распечатать некоторую часть объекта Reference Class, а не ID. Например, если я сопоставляю идентификаторы сотрудников (целое число) с классом "Сотрудник", мне бы хотелось, чтобы мои
data.frame
печатать имена сотрудников, а не их удостоверения личности. - Я хотел бы иметь возможность извлекать объекты непосредственно из
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