Ich habe ein Paket mit benutzerdefinierten summary()
, print()
Methoden für Objekte, die eine bestimmte Klasse haben. Dieses Paket verwendet auch das wunderbare Paket dplyr
zur Datenbearbeitung - und ich erwarte, dass meine Benutzer Skripte schreiben, die sowohl mein Paket als auch dplyr verwenden.definieren benutzerdefinierte dplyr Methoden in R Paket
Eine Straßensperre, die von anderen bemerkt wurde here und here ist, dass dplyr Verben keine benutzerdefinierten Klassen erhalten - was bedeutet, dass ein ungroup
Befehl meine data.frames ihrer benutzerdefinierten Klassen abstreifen können und somit Methode Dispatch vermasseln für summary
usw.
Hadley sagt „dies richtig tun, ist bis zu Ihnen - Sie benötigen ein Verfahren für Ihre Klasse für jede dplyr Methode zu definieren, die alle Klassen korrekt wieder her und Attribute“ und ich versuche, die advice zu nehmen - aber ich kann nicht herausfinden, wie man die dplyr-Verben richtig einpackt.
Hier ist ein einfaches Spielzeugbeispiel. Lassen Sie uns sagen, ich habe eine cars
Klasse definiert, und ich habe eine benutzerdefinierte summary
dafür.
das funktioniert
library(tidyverse)
class(mtcars) <- c('cars', class(mtcars))
summary.cars <- function(x, ...) {
#gather some summary stats
df_dim <- dim(x)
quantile_sum <- map(mtcars, quantile)
cat("A cars object with:\n")
cat(df_dim[[1]], 'rows and ', df_dim[[2]], 'columns.\n')
print(quantile_sum)
}
summary(mtcars)
hier ist das Problem
small_cars <- mtcars %>% filter(cyl < 6)
summary(small_cars)
class(small_cars)
dass summary
Ruf nach small_cars
gibt mir nur die allgemeine Zusammenfassung, nicht meine eigene Methode, weil small_cars
nicht mehr behält die cars
Klasse nach dplyr Filterung.
was habe ich versucht,
Zuerst habe ich versucht, eine benutzerdefinierte Methode um filter
Schreiben (filter.cars
). Das hat nicht funktioniert, weil filter
tatsächlich ein Wrapper um filter_
, die nicht standardmäßige Auswertung ermöglicht.
Also schrieb ich eine benutzerdefinierte filter_
Methode für cars
Objekte, versucht ‚zu implementieren @jwdink s advice
filter_.cars <- function(df, ...) {
old_classes <- class(df)
out <- dplyr::filter_(df, ...)
new_classes <- class(out)
class(out) <- c(new_classes, old_classes) %>% unique()
out
}
Das funktioniert nicht - ich eine unendliche Rekursion Fehler:
Error: evaluation nested too deeply: infinite recursion/options(expressions=)?
Error during wrapup: evaluation nested too deeply: infinite recursion/options(expressions=)?
Alles, was ich tun möchte, ist, die Klassen auf dem eingehenden df zu packen, an dplyr zu übergeben und dann das Objekt mit den gleichen Klassennamen wie vor dem dplyr-Aufruf zurückzugeben. Wie ändere ich meinen filter_
Wrapper, um das zu erreichen? Danke!
Ich mag Ihr letztes Beispiel, obwohl ich denke, 'reclass (data, NextMethod())' muss in 'reclass (.data, NextMethod()) geändert werden.' – Eric
Während es eine nette Abhilfe ist, scheint es nicht sehr vernünftig für ** dplyr ** um die Klassen zu löschen. Diese Problemumgehung bedeutet, dass jedes Paket, das benutzerdefinierte Datenrahmenklassen verwendet, nun Methoden für jedes ** dplyr ** Verb hinzufügen muss ... – Deleet
Eric, Ich habe den Tippfehler mit '.data' gegenüber' data' behoben (I didn merke es erst, wenn ich versucht habe, den Code selbst zu implementieren. – Deleet