Hi, I have questions about object attributes, and how they are handled when subsetted. My examples will use: tm <- (1:10)/10 ds <- (1:10)^2 attr(tm,"units") <- "sec" attr(ds,"units") <- "cm" dat <- data.frame(tm=tm,ds=ds) attr(dat,"id") <- "test1" When a "primitive class" object (numeric, character, etc.) is subsetted, the attributes are often stripped away, but the rules change for more complex classes, such as a data.frame, where they 'stick' for the data.frame, but attributes from the members are lost: tm[3:5] # lost ds[-3] # lost str(dat[1:3,]) # only kept for data.frame Is there any way of keeping the attributes when subsetted from primitive classes, like a fictional "attr.drop" option within the "[" braces? The best alternative I have found is to make a new object, and copy the attributes: tm2 <- tm[3:5] attributes(tm2) <- attributes(tm) However, for the data.frame, how can I copy the attributes over (without using a for loop -- I've tried a few things using sapply but no success)? Also I don't see how this is consistent with an empty index, "[]", where attributes are always retained (as documented): tm[] I have other concerns about the evaluation of objects with attributes (e.g. ds/tm), where the attributes from the first object are retained for the output, but this evaluation of logic is a whole other can of worms I'd rather keep closed for now. +mt
You can define your own class then define [ to act any way you would like: "[.myobj" <- function(x, ...) { y <- unclass(x)[...] attributes(y) <- attributes(x) y } tm <- structure(1:10, units = "sec", class = "myobj") tm tm[3:4] # still has attributes On 10/11/06, Michael Toews <mwtoews at ucalgary.ca> wrote:> Hi, > I have questions about object attributes, and how they are handled when > subsetted. My examples will use: > tm <- (1:10)/10 > ds <- (1:10)^2 > attr(tm,"units") <- "sec" > attr(ds,"units") <- "cm" > dat <- data.frame(tm=tm,ds=ds) > attr(dat,"id") <- "test1" > > When a "primitive class" object (numeric, character, etc.) is subsetted, > the attributes are often stripped away, but the rules change for more > complex classes, such as a data.frame, where they 'stick' for the > data.frame, but attributes from the members are lost: > tm[3:5] # lost > ds[-3] # lost > str(dat[1:3,]) # only kept for data.frame > > Is there any way of keeping the attributes when subsetted from primitive > classes, like a fictional "attr.drop" option within the "[" braces? The > best alternative I have found is to make a new object, and copy the > attributes: > tm2 <- tm[3:5] > attributes(tm2) <- attributes(tm) > > However, for the data.frame, how can I copy the attributes over (without > using a for loop -- I've tried a few things using sapply but no success)? > Also I don't see how this is consistent with an empty index, "[]", where > attributes are always retained (as documented): > tm[] > > I have other concerns about the evaluation of objects with attributes > (e.g. ds/tm), where the attributes from the first object are retained > for the output, but this evaluation of logic is a whole other can of > worms I'd rather keep closed for now. > > +mt > > ______________________________________________ > R-help at stat.math.ethz.ch mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >
Michael Toews wrote:> Hi, > I have questions about object attributes, and how they are handled when > subsetted. My examples will use: > tm <- (1:10)/10 > ds <- (1:10)^2 > attr(tm,"units") <- "sec" > attr(ds,"units") <- "cm" > dat <- data.frame(tm=tm,ds=ds) > attr(dat,"id") <- "test1" > > When a "primitive class" object (numeric, character, etc.) is subsetted, > the attributes are often stripped away, but the rules change for more > complex classes, such as a data.frame, where they 'stick' for the > data.frame, but attributes from the members are lost: > tm[3:5] # lost > ds[-3] # lost > str(dat[1:3,]) # only kept for data.frame > > Is there any way of keeping the attributes when subsetted from primitive > classes, like a fictional "attr.drop" option within the "[" braces? The > best alternative I have found is to make a new object, and copy the > attributes: > tm2 <- tm[3:5] > attributes(tm2) <- attributes(tm) > > However, for the data.frame, how can I copy the attributes over (without > using a for loop -- I've tried a few things using sapply but no success)? > Also I don't see how this is consistent with an empty index, "[]", where > attributes are always retained (as documented): > tm[] > > I have other concerns about the evaluation of objects with attributes > (e.g. ds/tm), where the attributes from the first object are retained > for the output, but this evaluation of logic is a whole other can of > worms I'd rather keep closed for now. > > +mt >This has been a tricky issue and for a long time I've wanted a system option( ) that would specify attributes that automatically survive subscripting. Since we don't have that, I have [. methods for objects with label and/or units attributes in the Hmisc package. -- Frank E Harrell Jr Professor and Chair School of Medicine Department of Biostatistics Vanderbilt University
This issue is discussed in much more detail in the manuals for 2.4.0, in particular in the new 'R Internals' manual. You will find the basic rules in the Blue Book (Becker, Chambers, Wilks, 1988) but they have not always been applied consistently. On Wed, 11 Oct 2006, Michael Toews wrote:> Hi, > I have questions about object attributes, and how they are handled when > subsetted. My examples will use: > tm <- (1:10)/10 > ds <- (1:10)^2 > attr(tm,"units") <- "sec" > attr(ds,"units") <- "cm" > dat <- data.frame(tm=tm,ds=ds) > attr(dat,"id") <- "test1" > > When a "primitive class" object (numeric, character, etc.) is subsetted, > the attributes are often stripped away, but the rules change for more > complex classes, such as a data.frame, where they 'stick' for the > data.frame, but attributes from the members are lost: > tm[3:5] # lost > ds[-3] # lost > str(dat[1:3,]) # only kept for data.frame > > Is there any way of keeping the attributes when subsetted from primitive > classes, like a fictional "attr.drop" option within the "[" braces? The > best alternative I have found is to make a new object, and copy the > attributes: > tm2 <- tm[3:5] > attributes(tm2) <- attributes(tm) > > However, for the data.frame, how can I copy the attributes over (without > using a for loop -- I've tried a few things using sapply but no success)? > Also I don't see how this is consistent with an empty index, "[]", where > attributes are always retained (as documented): > tm[] > > I have other concerns about the evaluation of objects with attributes > (e.g. ds/tm), where the attributes from the first object are retained > for the output, but this evaluation of logic is a whole other can of > worms I'd rather keep closed for now. > > +mt > > ______________________________________________ > R-help at stat.math.ethz.ch mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >-- Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
Michael Toews <mwtoews at ucalgary.ca> wrote:> Is there any way of keeping the attributes when subsetted from primitive > classes, like a fictional "attr.drop" option within the "[" braces? The > best alternative I have found is to make a new object, and copy the > attributes: > tm2 <- tm[3:5] > attributes(tm2) <- attributes(tm)> However, for the data.frame, how can I copy the attributes over (without > using a for loop -- I've tried a few things using sapply but no success)? > Also I don't see how this is consistent with an empty index, "[]", where > attributes are always retained (as documented): > tm[]What I've done is to define a subclass that keeps attributes, that can be added to any object, shown below. The keep.attr() function is supposed to return just user attributes but I'm not sure if my list of special ones is complete. I haven't looked at the performance impact of this sort of thing. -- David Hinds ---------------- keep.attr <- function(x) { a <- attributes(x) a[c('names','row.names','class','dim','dimnames')] <- NULL a } keep <- function(x, ..., attr=NULL) { cl <- union('keep', class(x)) do.call('structure', c(list(x, class=cl, ..., attr)) } '[.keep' <- function(x, ...) keep(NextMethod(), keep.attr(x)) '[<-.keep' <- function(x, ...) keep(NextMethod(), keep.attr(x)) tm <- keep((1:10)/10, units='sec') ds <- keep((1:10)^2, units='cm') dat <- data.frame(tm=tm,ds=ds) str(dat) tm[3:5] ds[-3] str(dat[1:3,]) str(dat[,1]) str(dat[1]) dat <- keep(dat, parent='xyz') str(dat) str(dat[2,2])
Apparently Analagous Threads
- Rgui.exe plot device "Save as" crash (PR#9237)
- 'virsh capabilities' on Debian Wheezy-amd64 reports different cpu to Wheezy-i386 (on same hardware)
- Live Migration and LibVirt CPU Mode
- Re: 'virsh capabilities' on Debian Wheezy-amd64 reports different cpu to Wheezy-i386 (on same hardware)
- Re: 'virsh capabilities' on Debian Wheezy-amd64 reports different cpu to Wheezy-i386 (on same hardware)