I'm sending this to r-devel rather than r-help as I suspect I'm pushing the boundaries of the R language. In that I get no errors but things don't "work", I may have revealed a gap in the attributes structure. In displaying results of some optimization calculations (in the optimx package I maintain), I'd like to add indicators F(ree), L(ower) and U(pper) to indicate if parameters returned are on bounds. I've got my optimr() routine to put the character indicators in the list() structure of the answer to each individual solver result. However, when I collect these into a data frame for the results of several solvers (run by the opm() function), it seems that attributes can't be carried through. Here is a small example. pp<-c(1,2) attr(pp[1], "trial")<-"first" attributes(pp) attributes(pp[1]) attr(pp[1],"trial") pp[1] pp[2] attr(pp, "name")<-"rubbish" attributes(pp) str(pp) The output is: > pp<-c(1,2) > attr(pp[1], "trial")<-"first" ## APPEARS TO ACCEPT ATTRIBUTE > attributes(pp) NULL > attributes(pp[1]) NULL > attr(pp[1],"trial") ## FAILS TO FIND ATTRIBUTE NULL > pp[1] [1] 1 > pp[2] [1] 2 > attr(pp, "name")<-"rubbish" > attributes(pp) $name [1] "rubbish" > str(pp) num [1:2] 1 2 - attr(*, "name")= chr "rubbish" Similarly, pl<-list(one=1, two=2) attr(pl[1],"trial")<- "lfirst" attr(pl[1], "trial") attributes(pl) attributes(pl[1]) attributes(pl$one) str(pl) This also fails. Am I doing something silly? Thanks in advance for any pointers. JN
On Tue, 22 Feb 2022 13:29:15 -0500 J C Nash <profjcnash at gmail.com> wrote:> pp<-c(1,2) > attr(pp[1], "trial")<-"first"I don't have a solid proof for this with a link to the R Language Definition, but my understanding of the attributes is that they belong to the whole vector (and that elements of a vector don't usually exist as separate entities in R). Maybe this explains why the attribute of a temporary value is lost in this assignment.> pl<-list(one=1, two=2) > attr(pl[1],"trial")<- "lfirst"However, this could be made to work, if attributes were assigned on the list element instead of the list slice: attr(pl[[1]],"trial")<- "lfirst" attr(pl[[1]],"trial") # [1] "lfirst" Same goes for data.frame columns: str(data.frame(x = 1:10, y = structure(1:10, attr = 'val'))) # 'data.frame': 10 obs. of 2 variables: # $ x: int 1 2 3 4 5 6 7 8 9 10 # $ y: atomic 1 2 3 4 5 6 7 8 9 10 # ..- attr(*, "attr")= chr "val" # <-- attribute preserved If you need to tag rows of a data frame, your best bet would likely be to assign a vector as an attribute of the data frame itself. -- Best regards, Ivan
On Tue, 22 Feb 2022 at 19:29, J C Nash <profjcnash at gmail.com> wrote:> > I'm sending this to r-devel rather than r-help as I suspect I'm pushing the boundaries > of the R language. In that I get no errors but things don't "work", I may have revealed > a gap in the attributes structure. > > In displaying results of some optimization calculations (in the optimx package I maintain), > I'd like to add indicators F(ree), L(ower) and U(pper) to indicate if parameters returned are > on bounds. I've got my optimr() routine to put the character indicators in the list() structure of > the answer to each individual solver result. However, when I collect these into a data frame > for the results of several solvers (run by the opm() function), it seems that attributes > can't be carried through. > > Here is a small example. > > pp<-c(1,2) > attr(pp[1], "trial")<-"first" > attributes(pp) > attributes(pp[1]) > attr(pp[1],"trial") > pp[1] > pp[2] > attr(pp, "name")<-"rubbish" > attributes(pp) > str(pp) > > The output is: > > > pp<-c(1,2) > > > attr(pp[1], "trial")<-"first" ## APPEARS TO ACCEPT ATTRIBUTE > > > attributes(pp) > NULL > > > attributes(pp[1]) > NULL > > > attr(pp[1],"trial") ## FAILS TO FIND ATTRIBUTE > NULL > > > pp[1] > [1] 1 > > > pp[2] > [1] 2 > > > attr(pp, "name")<-"rubbish" > > > attributes(pp) > $name > [1] "rubbish" > > > > str(pp) > num [1:2] 1 2 > - attr(*, "name")= chr "rubbish" > > Similarly, > > pl<-list(one=1, two=2) > attr(pl[1],"trial")<- "lfirst" > attr(pl[1], "trial") > attributes(pl) > attributes(pl[1]) > attributes(pl$one) > str(pl) > > This also fails. > > Am I doing something silly? > > Thanks in advance for any pointers.In short, this is not how it works. In both cases, you are assigning an attribute to a temporary subset that is immediately destroyed, because it's not assigned to anything. So you are doing this: pp<-c(1,2) tmp <- pp[1] attr(tmp, "trial")<-"first" rm(tmp) The assignment of course succeeds, but that's not what you want. What you can do is to add a data.frame of size length(pp) as an attribute to pp, with as many columns as you need (lower, upper...). -- I?aki ?car