And as a follow-up, I implemented a barebones as.data.frame.MyClass(...).
It works when dealing with non-subsetted data frames, but fails upon a
subset(...) call:
> as.data.frame.MyClass <- function(x, ...) as.data.frame.vector(x, ...)
This works for a single column, e.g.:
> str(data.frame(MyClass(1:10)))
'data.frame': 10 obs. of 1 variable:
$ MyClass.1.10.:Class 'MyClass' int [1:10] 1 2 3 4 5 6 7 8 9 10
But not during a subset:
> str(subset(data.frame(x = MyClass(1:10)), x %% 2 == 0))
'data.frame': 5 obs. of 1 variable:
$ x: int 2 4 6 8 10
-Murat
On Wed, Nov 12, 2014 at 10:02 PM, Murat Tasan <mmuurr at gmail.com>
wrote:> Hi all --- I've stumbled upon some pretty annoying behavior, and
I'm
> curious how others may have gotten around it.
> When using subset(...) on a data frame that contains a custom S3
> field, the class is dropped in the result:
>
>> MyClass <- function(x) structure(x, class = "MyClass")
>
>> df <- data.frame(x = 1:10, y = 10:1)
>> df$x <- MyClass(df$x)
>> str(df)
> 'data.frame': 10 obs. of 2 variables:
> $ x:Class 'MyClass' int [1:10] 1 2 3 4 5 6 7 8 9 10
> $ y: int 10 9 8 7 6 5 4 3 2 1
>> str(subset(df, x %% 2 == 0))
> 'data.frame': 5 obs. of 2 variables:
> $ x: int 2 4 6 8 10
> $ y: int 9 7 5 3 1
>
> And so, any generic functions hooked to MyClass suddenly don't work on
> the subset results, but do work on the original data frame.
> I think I could write a custom as.data.frame.MyClass for all such
> classes, but this is annoying, indeed (and I don't know for sure if
> that's a robust solution)
> Wrapping in I(...) doesn't work, either:
>
>> df <- data.frame(x = 1:10, y = 10:1)
>> df$x <- I(MyClass(df$x))
>> str(df)
> 'data.frame': 10 obs. of 2 variables:
> $ x:Classes 'AsIs', 'MyClass' int [1:10] 1 2 3 4 5 6 7 8
9 10
> $ y: int 10 9 8 7 6 5 4 3 2 1
>> str(subset(df, x %% 2 == 0))
> 'data.frame': 5 obs. of 2 variables:
> $ x:Class 'AsIs' int [1:5] 2 4 6 8 10
> $ y: int 9 7 5 3 1
>
> (note that while 'AsIs' is kept, 'MyClass' has been removed
in $x)
>
> Cheers!
>
> -Murat