[R] subset drops S3 classes?

Murat Tasan mmuurr at gmail.com
Thu Nov 13 07:21:17 CET 2014


... aaaand nevermind, figured it out (from the final example on the
Extract.data.frame page):

`[.MyClass` <- function(x, i, ...) {
    NextMethod("[")
    mostattributes(RV) <- attribute(x)
    RV
}

cheers,

-m

On Wed, Nov 12, 2014 at 11:02 PM, Murat Tasan <mmuurr at gmail.com> wrote:
> 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



More information about the R-help mailing list