Я работаю с R и создал новый метод subset для объектов класса new_object. Вот моя функция:
setGeneric('subset', function(x, i) standardGeneric('subset'))
setMethod('subset', 'new_object', function(x, i) {
# ... my code ...
# subset new_object
})
Это отлично работает для new_object. Однако, похоже, это мешает работе подмножества других объектов, например объектов seurat. Я получаю сообщение об ошибке, когда пытаюсь подмножество объекта seurat после загрузки нового метода подмножества.
The inheritance method for the 'subset' function with the 'Seurat' tag could not be found.
Я бы хотел, чтобы метод subset работал как обычно для всех остальных типов объектов, кроме new_object, для которого я хочу использовать свой новый метод subset.
Как я могу определить новый метод подмножества для определенного класса, не затрагивая другие объекты в R?





В чистом, только что открытом R запустите subset без фигурных скобок, чтобы увидеть, что это за объект.
> subset
function (x, ...)
UseMethod("subset")
<bytecode: 0x0000019b6e422730>
<environment: namespace:base>
Итак, это универсальная функция S3 с аргументами x, ... и находится в пакете base. Таким образом, когда вы вызываете setGeneric('subset', function(x, i) standardGeneric('subset')), вы создаете новую универсальную функцию с аргументами x, i, которая отличается от существующих аргументов x, ... для subset, определенных в пакете base.
Решение состоит в том, чтобы вызвать setGeneric("subset"), чтобы существующая функция (subset в пакете base) стала универсальной функцией S4.
> setGeneric("subset")
> setClass("new_object")
> setMethod("subset", "new_object", function(x, i, ...) {
# ... your code here ...
# subset new_object
# below is an example
print(x)
})
> subset
standardGeneric for "subset" defined from package "base"
function (x, ...)
standardGeneric("subset")
<environment: 0x000001f4839ab3b8>
Methods may be defined for arguments: x
Use showMethods(subset) for currently available ones.
> showMethods("subset", includeDefs = TRUE)
Function: subset (package base)
x = "ANY"
function (x, ...)
UseMethod("subset")
x = "new_object"
function (x, ...)
{
.local <- function (x, i, ...)
{
print(x)
}
.local(x, ...)
}
Как вы можете видеть из showMethods("subset", includeDefs = TRUE), когда вы вызываете этот S4 subset с помощью x класса new_object, он будет отправлен в ваши пользовательские методы. При вызове любого другого класса он будет использовать существующий механизм диспетчеризации S3 (т. е. UseMethod).
Примечание. Хорошей практикой является использование в вашем методе всех аргументов универсального метода, включая… если в данном случае универсальный аргумент есть, setMethod("subset", "new_object", function(x, i, ...) {# your code here ...} (большое спасибо @JDL за то, что познакомил меня с этим моментом).
Спасибо за ответ, он очень хорошо отвечает на мой вопрос. На самом деле я не очень хорошо знаком с объектами в языке R, поскольку они сильно отличаются от таких языков, как Python. Не могли бы вы объяснить здесь назначение setGeneric() и setMethod()? Похоже, что setGeneric определяет функцию, а setMethod определяет реализацию этой функции?
@zhang Предлагаю вам прочитать главу Advanced R, написанную Хэдли Уикхэмом по S4: adv-r.had.co.nz/S4.html
@zhang Можете ли вы сделать это вопросом вместо комментария? Я постараюсь ответить на него. Раздел комментариев довольно мал для таких вещей. Кроме того, ссылка, предоставленная SamR, предназначена для старой версии Advanced R, новая версия: https://adv-r.hadley.nz/s4.html
кстати, я бы рекомендовал добавить "..." в качестве аргумента вашего метода, даже если он вам не нужен, потому что это аргумент общего метода. в руководстве по написанию расширений R объясняется, почему рекомендуется это делать.
@JDL большое спасибо за ваш вклад. Первоначально я видел, что WRE ограничивает обсуждение S3, но, подумав некоторое время, я думаю, что его совет применим и к S4.
Возможно это: stackoverflow.com/a/12712646/1412059