Re: [R] extract parts of a list before symbol
All true Jeff, but why do things the easy way! LOL! My point was that various data structures, besides the list we started with, store the names as an attribute. Yes, names(listname) works fine to extract whatever parts they want. My original idea of using a data.frame was because it creates names when they are absent. And you are correct that if the original list was not as shown with only all items of length 1, converting to a data.frame fails. >From what you say, it is a harder think to write a function that returns a "name" for column N given a list. As you note, you get a null when there are no names. You get empty strings when one or more (but not all) have no names. But it can be done. The OP initially was looking at a way to get a text version of a variable they could use using perhaps regular expressions to parse. Of course that is not as easy as just looking at the names attribute in one of several ways. But it may help in a sense to deal with the cases mentioned above. The problem is that str() does not return anything except to stdout so it must be captured to do silly things. > test <- list(a=3,b=5,c=11) > str(test) List of 3 $ a: num 3 $ b: num 5 $ c: num 11 > str(test[1]) List of 1 $ a: num 3 > str(test[2]) List of 1 $ b: num 5 > str(list(a=1, 2, c=3)) List of 3 $ a: num 1 $ : num 2 $ c: num 3 > str(list(1, 2, 3)) List of 3 $ : num 1 $ : num 2 $ : num 3 > text <- str(list(a=1, 2, c=3)[1]) List of 1 $ a: num 1 > text <- capture.output(str(list(a=1, 2, c=3))) > text [1] "List of 3" " $ a: num 1" " $ : num 2" " $ c: num 3" So you could use some imaginative code that extracts what you want. I repeat, this is not a suggested way nor the best, just something that seems to work: > sub("(^[\\$ ]*)(\\w+|)(:.*$)", "\\2", text[2:length(text)]) [1] "a" "" "c" Obviously the first line of output needs to be removed as it does not fit the pattern. Perhaps in this case a way less complex way is to use summary() rather than str as it does return the output as text. > summary(list(a=1, 2, c=3)) -> text > text Length Class Mode a 1 -none- numeric 1 -none- numeric c 1 -none- numeric This puts the variable name, if any, at the start but parsing that is not trivial as it is not plain text. Bottom line, try not to do things the hard way. Just carefully use names() ... -Original Message- From: R-help On Behalf Of Jeff Newmiller Sent: Thursday, May 25, 2023 10:32 PM To: r-help@r-project.org Subject: Re: [R] extract parts of a list before symbol What a remarkable set of detours, Avi, all deriving apparently from a few gaps in your understanding of R. As Rolf said, "names(test)" is the answer. a) Lists are vectors. They are not atomic vectors, but they are vectors, so as.vector(test) is a no-op. test <- list( a = 1, b = 2, c=3 ) attributes(test) attributes(as.vector(test)) (Were you thinking of the unlist function? If so, there is no reason to convert the value of the list to an atomic vector in order to look at the value of an attribute of that list.) b) Data frames are lists, with the additional constraint that all elements have the same length, and that a names attribute and a row.names attribute are both required. Converting a list to a data frame to get the names is expensive in CPU cycles and breaks as soon as the list elements have a variety of lengths. c) All data in R is stored as vectors. Worrying about whether a data value is a vector is pointless. d) All objects can have attributes, including the name attribute. However, not all objects must have a name attribute... including lists. Omitting a name for any of the elements of a list in the constructor will lead to having a zero-length character values in the name attribute where the names were omitted. Omitting all names in the list constructor will cause no names attribute to be created for that list. test2 <- list( 1, 2, 3 ) attributes(test2) e) The names() function returns the value of the names attribute. If that attribute is missing, it returns NULL. For dataframes, the colnames function is equivalent to the names function (I rarely use the colnames function). For lists, colnames returns NULL... there are no "columns" in a list, because there is no constraint on the (lengths of the) contents of a list. names(test2) f) The names attribute, if it exists, is just a character vector. It is never necessary to convert the output of names() to a character vector. If the names attribute doesn't exist, then it is up to the user to write code that creates it. names(test2) <- c( "A", "B", "C" ) attributes(test2) names(test2) # or use the argument names in the list function names(test2) <- 1:3 # integer names(test2) # character attributes(test2)$names <- 1:3 # integer attributes(test2) # character test2[[ "2" ]] == 2 # TRUE test2$`2` == 2 # TRUE On May 25, 2023 6:17:37 PM PDT, avi.e.gr...@gmail.com wrote: >Evan, > >List names are less easy than data.frame column names so
Re: [R] extract parts of a list before symbol
What a remarkable set of detours, Avi, all deriving apparently from a few gaps in your understanding of R. As Rolf said, "names(test)" is the answer. a) Lists are vectors. They are not atomic vectors, but they are vectors, so as.vector(test) is a no-op. test <- list( a = 1, b = 2, c=3 ) attributes(test) attributes(as.vector(test)) (Were you thinking of the unlist function? If so, there is no reason to convert the value of the list to an atomic vector in order to look at the value of an attribute of that list.) b) Data frames are lists, with the additional constraint that all elements have the same length, and that a names attribute and a row.names attribute are both required. Converting a list to a data frame to get the names is expensive in CPU cycles and breaks as soon as the list elements have a variety of lengths. c) All data in R is stored as vectors. Worrying about whether a data value is a vector is pointless. d) All objects can have attributes, including the name attribute. However, not all objects must have a name attribute... including lists. Omitting a name for any of the elements of a list in the constructor will lead to having a zero-length character values in the name attribute where the names were omitted. Omitting all names in the list constructor will cause no names attribute to be created for that list. test2 <- list( 1, 2, 3 ) attributes(test2) e) The names() function returns the value of the names attribute. If that attribute is missing, it returns NULL. For dataframes, the colnames function is equivalent to the names function (I rarely use the colnames function). For lists, colnames returns NULL... there are no "columns" in a list, because there is no constraint on the (lengths of the) contents of a list. names(test2) f) The names attribute, if it exists, is just a character vector. It is never necessary to convert the output of names() to a character vector. If the names attribute doesn't exist, then it is up to the user to write code that creates it. names(test2) <- c( "A", "B", "C" ) attributes(test2) names(test2) # or use the argument names in the list function names(test2) <- 1:3 # integer names(test2) # character attributes(test2)$names <- 1:3 # integer attributes(test2) # character test2[[ "2" ]] == 2 # TRUE test2$`2` == 2 # TRUE On May 25, 2023 6:17:37 PM PDT, avi.e.gr...@gmail.com wrote: >Evan, > >List names are less easy than data.frame column names so try this: > >> test <- list(a=3,b=5,c=11) >> colnames(test) >NULL >> colnames(as.data.frame(test)) >[1] "a" "b" "c" > >But note an entry with no name has one made up for it. > > >> test2 <- list(a=3,b=5, 666, c=11) >> colnames(data.frame(test2)) >[1] "a""b""X666" "c" > >But that may be overkill as simply converting to a vector if ALL parts are >of the same type will work too: > >> names(as.vector(test)) >[1] "a" "b" "c" > >To get one at a time: > >> names(as.vector(test))[1] >[1] "a" > >You can do it even simple by looking at the attributes of your list: > >> attributes(test) >$names >[1] "a" "b" "c" > >> attributes(test)$names >[1] "a" "b" "c" >> attributes(test)$names[3] >[1] "c" > > >-Original Message- >From: R-help On Behalf Of Evan Cooch >Sent: Thursday, May 25, 2023 1:30 PM >To: r-help@r-project.org >Subject: [R] extract parts of a list before symbol > >Suppose I have the following list: > >test <- list(a=3,b=5,c=11) > >I'm trying to figure out how to extract the characters to the left of >the equal sign (i.e., I want to extract a list of the variable names, a, >b and c. > >I've tried the permutations I know of involving sub - things like >sub("\\=.*", "", test), but no matter what I try, sub keeps returning >(3, 5, 11). In other words, even though I'm trying to extract the >'stuff' before the = sign, I seem to be successful only at grabbing the >stuff after the equal sign. > >Pointers to the obvious fix? Thanks... > >__ >R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see >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. > >__ >R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see >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. -- Sent from my phone. Please excuse my brevity. __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see 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.
Re: [R] extract parts of a list before symbol
Evan, List names are less easy than data.frame column names so try this: > test <- list(a=3,b=5,c=11) > colnames(test) NULL > colnames(as.data.frame(test)) [1] "a" "b" "c" But note an entry with no name has one made up for it. > test2 <- list(a=3,b=5, 666, c=11) > colnames(data.frame(test2)) [1] "a""b""X666" "c" But that may be overkill as simply converting to a vector if ALL parts are of the same type will work too: > names(as.vector(test)) [1] "a" "b" "c" To get one at a time: > names(as.vector(test))[1] [1] "a" You can do it even simple by looking at the attributes of your list: > attributes(test) $names [1] "a" "b" "c" > attributes(test)$names [1] "a" "b" "c" > attributes(test)$names[3] [1] "c" -Original Message- From: R-help On Behalf Of Evan Cooch Sent: Thursday, May 25, 2023 1:30 PM To: r-help@r-project.org Subject: [R] extract parts of a list before symbol Suppose I have the following list: test <- list(a=3,b=5,c=11) I'm trying to figure out how to extract the characters to the left of the equal sign (i.e., I want to extract a list of the variable names, a, b and c. I've tried the permutations I know of involving sub - things like sub("\\=.*", "", test), but no matter what I try, sub keeps returning (3, 5, 11). In other words, even though I'm trying to extract the 'stuff' before the = sign, I seem to be successful only at grabbing the stuff after the equal sign. Pointers to the obvious fix? Thanks... __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see 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. __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see 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.
Re: [R] extract parts of a list before symbol
On Thu, 25 May 2023 13:29:52 -0400 Evan Cooch wrote: > Suppose I have the following list: > > test <- list(a=3,b=5,c=11) > > I'm trying to figure out how to extract the characters to the left of > the equal sign (i.e., I want to extract a list of the variable names, > a, b and c. > > I've tried the permutations I know of involving sub - things like > sub("\\=.*", "", test), but no matter what I try, sub keeps returning > (3, 5, 11). In other words, even though I'm trying to extract the > 'stuff' before the = sign, I seem to be successful only at grabbing > the stuff after the equal sign. > > Pointers to the obvious fix? Thanks... Perhaps names(test) ??? cheers, Rolf Turner -- Honorary Research Fellow Department of Statistics University of Auckland Stats. Dep't. (secretaries) phone: +64-9-373-7599 ext. 89622 Home phone: +64-9-480-4619 __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see 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.
[ESS] brms / cmdstanr crashes in emacs but not terminal
Hi All, I normally work in Emacs (28.2 build 2)) on Windows 11 pro as an admin user. Quite a few of my analyses these days use Stan (via cmdstanr and the brms package as example). I upgraded R to 4.3.0 and Stan. Now, I am quite reliably getting crashes where my R process terminates when using Stan. For those not familiar, Stan is in C++ and generates code which is then compiled into a custom C++ model for that Bayesian analysis. The compilation is fine, but when it starts sampling, I get this when I run via Emacs: ## Start sampling ## > > ## Process R finished at Fri May 26 10:32:05 2023 The reason I'm asking here and not just on Stan forums is that when I start a terminal (cmd.exe) and start R there and run the exact same code, it reliably finishes and does not crash. I also tried M-x shell in Emacs and running R through that and also get a crash. If anyone knows a solution that would be great but at this stage I'd love to hear even just ideas on _what_ the difference is? I guess in my head R through terminal and R through Emacs were the same and so I'm not sure where to even begin looking for causes. Many thanks, Josh [[alternative HTML version deleted]] __ ESS-help@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/ess-help
Re: [R] environments: functions within functions
Thank you to both Duncan and Ivan for the detailed answers. I'll point the mixR maintainer at this thread in the list archive, because your suggestions were so clear, and I can't explain them as thoroughly. I'll keep using x as the argument name for now. Much appreciated, Sarah On Thu, May 25, 2023 at 10:18 AM Sarah Goslee wrote: > > Hi, > > I ran into a problem with S3 method dispatch and scoping while trying > to use functions from the mixR package within my own functions. I know > enough to find the problem (I think!), but not enough to fix it > myself. The problem isn't really a package-specific problem, so I'm > starting here, and will file an issue with the maintainer once I have > a solution. > > Detailed explanation below, but briefly, the S3 methods in this > package use match.call() and then eval() to select the correct > internal method. This works fine from the command line, but if the > method is called from within another function, the use of > environment() within eval() means that the objects passed to the > wrapper function are no longer visible within the eval() call. > > I have a two-part question: > A. How do I get around this right now? > B. What would the correct approach be for the package authors? > > library(mixR) > > # first example from ?mixfit > ## fitting the normal mixture models > set.seed(103) > x <- rmixnormal(200, c(0.3, 0.7), c(2, 5), c(1, 1)) > data <- bin(x, seq(-1, 8, 0.25)) > fit1 <- mixfit(x, ncomp = 2) # raw data > rm(x, data) > ### > > # simple function > funworks <- function(x) { > print(x) > } > > ### > > # almost identical simple function > funfails <- function(thisx) { > print(thisx) > } > > ### > > funworks(fit1) > funfails(fit1) > > ### > > The explanation as I understand it... > > print called on this object gets passed to print.mixfitEM(), which is: > > > function (x, digits = getOption("digits"), ...) > { > family <- x$family > mc <- match.call() > mc$digits <- digits > fun.name <- paste0("print", family) > mc[[1]] <- as.name(fun.name) > eval(mc, environment()) > } > > > Working through the calls, when eval() is called from within funfails(), mc is > printnormal(x = thisx, digits = 7) > and the calling environment does not contain thisx. > > In funworks(), it's > printnormal(x = x, digits = 7) > > and x is found. > > So, I can get around the problem by naming my argument x, as in > funworks(), but that's unsatisfying. Is there something else I can do > to get my functions to work? > > And what's the correct way to do what print.mixfitEM() is doing, so > that it works regardless? I poked around for a while, but didn't find > a clear (to me!) answer. > > Thanks, > Sarah > > -- > Sarah Goslee (she/her) > http://www.numberwright.com -- Sarah Goslee (she/her) http://www.numberwright.com __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see 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.
[R] extract parts of a list before symbol
Suppose I have the following list: test <- list(a=3,b=5,c=11) I'm trying to figure out how to extract the characters to the left of the equal sign (i.e., I want to extract a list of the variable names, a, b and c. I've tried the permutations I know of involving sub - things like sub("\\=.*", "", test), but no matter what I try, sub keeps returning (3, 5, 11). In other words, even though I'm trying to extract the 'stuff' before the = sign, I seem to be successful only at grabbing the stuff after the equal sign. Pointers to the obvious fix? Thanks... __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see 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.
Re: [R] data.frame with a column containing an array
Maybe... if you want it to act like a matrix... then you should... use a matrix... I think making this behaviour work with 2d arrays could be a feature, but making it work with higher dimension arrays would be difficult, and differentiating between 2d and higher dimension arrays could have just as unexpected behaviors as differentiating between matrices and 2d arrays is for you now. Arrays and matrices are supposed to be more compatible now than they used to be... specifying a matrix should work just as well as specifying a 2d array when it comes to whatever operations are leading you to want an array at all, and will close the door on trying to stuff a higher dimension array into the dataframe accidentally. ... or don't put it into a data frame? On May 25, 2023 10:15:00 AM PDT, Bert Gunter wrote: >I really don't know. I would call it a request for extended capabilities of >[.data.frame, rather than a feature or bug. But maybe wiser heads than mine >who monitor this list can sort it out. > >-- Bert > >On Wed, May 24, 2023 at 8:52 PM Georg Kindermann >wrote: > >> So is this an expected behavior or is it a bug which should be reported >> somewhere else? >> >> Thanks! >> Georg >> >> >> >> Gesendet: Dienstag, 09. Mai 2023 um 19:28 Uhr >> Von: "Bert Gunter" >> An: "Georg Kindermann" >> Cc: "Rui Barradas" , r-help@r-project.org >> Betreff: Re: [R] data.frame with a column containing an array >> >> >> >> I think the following may provide a clearer explanation: >> >> subs <- c(1,3) >> DFA <- data.frame(id = 1:3) >> ar <- array(1:12, c(3,2,2)) >> ## yielding >> > ar >> , , 1 >> >> [,1] [,2] >> [1,]14 >> [2,]25 >> [3,]36 >> >> , , 2 >> >> [,1] [,2] >> [1,]7 10 >> [2,]8 11 >> [3,]9 12 >> >> ## array subscripting gives >> > ar[subs,,] >> , , 1 >> >> [,1] [,2] >> [1,]14 >> [2,]36 >> >> , , 2 >> >> [,1] [,2] >> [1,]7 10 >> [2,]9 12 >> >> ## Now with df's >> > DFA[["ar"]] <- ar >> > >> > DFM <- data.frame(id = 1:3) >> > DFM[["M"]] <- matrix(1:6, nc =2) >> > >> > str(DFM) >> 'data.frame': 3 obs. of 2 variables: >> $ id: int 1 2 3 >> $ M : int [1:3, 1:2] 1 2 3 4 5 6 >> > str(DFA) >> 'data.frame': 3 obs. of 2 variables: >> $ id: int 1 2 3 >> $ ar: int [1:3, 1:2, 1:2] 1 2 3 4 5 6 7 8 9 10 ... >> > >> > ## But the data frame print method for these give >> > DFM >> id M.1 M.2 >> 1 1 1 4 >> 2 2 2 5 >> 3 3 3 6 >> > DFA >> id ar.1 ar.2 ar.3 ar.4 >> 1 1147 10 >> 2 2258 11 >> 3 3369 12 >> > >> > ## [.data.frame subscripting gives >> > DFA[subs,] >> id ar >> 1 1 1 >> 3 3 3 >> > DFM[subs,] >> id M.1 M.2 >> 1 1 1 4 >> 3 3 3 6 >> > >> > ## but explicit array subscripting of course works >> > DFA$ar[match(subs,DFA$id),,] >> , , 1 >> >> [,1] [,2] >> [1,]14 >> [2,]36 >> >> , , 2 >> >> [,1] [,2] >> [1,]7 10 >> [2,]9 12 >> >> >> Cheers, >> Bert >> > > [[alternative HTML version deleted]] > >__ >R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see >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. -- Sent from my phone. Please excuse my brevity. __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see 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.
Re: [R] data.frame with a column containing an array
I really don't know. I would call it a request for extended capabilities of [.data.frame, rather than a feature or bug. But maybe wiser heads than mine who monitor this list can sort it out. -- Bert On Wed, May 24, 2023 at 8:52 PM Georg Kindermann wrote: > So is this an expected behavior or is it a bug which should be reported > somewhere else? > > Thanks! > Georg > > > > Gesendet: Dienstag, 09. Mai 2023 um 19:28 Uhr > Von: "Bert Gunter" > An: "Georg Kindermann" > Cc: "Rui Barradas" , r-help@r-project.org > Betreff: Re: [R] data.frame with a column containing an array > > > > I think the following may provide a clearer explanation: > > subs <- c(1,3) > DFA <- data.frame(id = 1:3) > ar <- array(1:12, c(3,2,2)) > ## yielding > > ar > , , 1 > > [,1] [,2] > [1,]14 > [2,]25 > [3,]36 > > , , 2 > > [,1] [,2] > [1,]7 10 > [2,]8 11 > [3,]9 12 > > ## array subscripting gives > > ar[subs,,] > , , 1 > > [,1] [,2] > [1,]14 > [2,]36 > > , , 2 > > [,1] [,2] > [1,]7 10 > [2,]9 12 > > ## Now with df's > > DFA[["ar"]] <- ar > > > > DFM <- data.frame(id = 1:3) > > DFM[["M"]] <- matrix(1:6, nc =2) > > > > str(DFM) > 'data.frame': 3 obs. of 2 variables: > $ id: int 1 2 3 > $ M : int [1:3, 1:2] 1 2 3 4 5 6 > > str(DFA) > 'data.frame': 3 obs. of 2 variables: > $ id: int 1 2 3 > $ ar: int [1:3, 1:2, 1:2] 1 2 3 4 5 6 7 8 9 10 ... > > > > ## But the data frame print method for these give > > DFM > id M.1 M.2 > 1 1 1 4 > 2 2 2 5 > 3 3 3 6 > > DFA > id ar.1 ar.2 ar.3 ar.4 > 1 1147 10 > 2 2258 11 > 3 3369 12 > > > > ## [.data.frame subscripting gives > > DFA[subs,] > id ar > 1 1 1 > 3 3 3 > > DFM[subs,] > id M.1 M.2 > 1 1 1 4 > 3 3 3 6 > > > > ## but explicit array subscripting of course works > > DFA$ar[match(subs,DFA$id),,] > , , 1 > > [,1] [,2] > [1,]14 > [2,]36 > > , , 2 > > [,1] [,2] > [1,]7 10 > [2,]9 12 > > > Cheers, > Bert > [[alternative HTML version deleted]] __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see 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.
Re: [R] environments: functions within functions
(Sorry for the double post.) В Thu, 25 May 2023 18:53:45 +0300 Ivan Krylov пишет: > print(fit1) # tracer not called Interesting. There must be some caching involved. If print(a) is resolved to print.mixfitEM at least once, it keeps failing. In a fresh R session, where a trace()-patch is done before printing objects of this class, print(a) succeeds: trace(mixR:::print.mixfitEM, quote({ mc$x <- x }), at = 7) (function(a) print(a))(fit1) # this used to fail # Tracing print.mixfitEM(a) step 7 # Normal mixture model with 2 components #comp1 comp2 # pi 0.292 0.708 # mu 2.0140197 4.9837052 # sd 0.8896020 1.0273591 # # EM iterations: 78 AIC: 759.35 BIC: 775.84 log-likelihood: -374.67 -- Best regards, Ivan __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see 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.
Re: [R] environments: functions within functions
В Thu, 25 May 2023 10:18:13 -0400 Sarah Goslee пишет: > print called on this object gets passed to print.mixfitEM(), which is: > > > function (x, digits = getOption("digits"), ...) > { > family <- x$family > mc <- match.call() > mc$digits <- digits > fun.name <- paste0("print", family) > mc[[1]] <- as.name(fun.name) > eval(mc, environment()) > } > > > Working through the calls, when eval() is called from within > funfails(), mc is printnormal(x = thisx, digits = 7) > and the calling environment does not contain thisx. Your functions, both funworks and funfails, did nothing wrong. They are using R as intended, so there shouldn't be anything to fix. I think that mixR::mixfitEM is making a mistake in its use of non-standard evaluation. When working with match.call(), the typical pattern is to eval() the modified call in the parent.frame() (where the call had originated and where, presumably, all its referenced variables still live). mixR cannot use this pattern unaltered because they want to call an unexported function, e.g., mixR:::printnormal. The authors could construct a call to ::: and insert that into mc[[1]] instead of as.name(fun.name), so that the resulting call would be to mixR:::printnormal(remaining arguments) and would thus cleanly evaluate in the calling environment, but R CMD check could give them a NOTE for using ::: (even with their own package). One way to get around this would be to put the function itself in the first element of the call (i.e. mc[[1]] <- get(fun.name) instead of as.name(fun.name)), thus also making it possible to perform the call despite as.name(fun.name) cannot be resolved from parent.frame(). This could lead to scary-looking tracebacks. Another way would be to keep the environment of the call as it is, but evaluate the arguments from the matched call, something like: for (i in seq_along(mc)[-1]) mc[[i]] <- eval(mc[[i]], parent.frame()) This code is untested, but the idea is to remove any dependency of the matched call on the calling frame, thus making it possible to evaluate it without problems in the package environment. This will again lead to scary-looking tracebacks, potentially worse than the previous option (depending on whether deparse() is longer for mixR:::printnormal or its typical arguments), and will also wreak havoc on any additional use of non-standard evaluation by printnormal (hopefully there isn't any, but any arguments that should have stayed quoted will be evaluated instead). They already do something like this with the digits=... argument. I could also suggest a redesign of the package to make fuller use of the S3 dispatch system (i.e. prepend x$family to class(x), possibly with a package-specific prefix and make printnormal() and friends into S3 methods for print()) instead of trying to implement it oneself, but I understand that it may be not an available option. I was going to suggest patching around the bug using trace(), but it doesn't seem to work well with S3 method dispatch. No matter what I do, UseMethod() seems to pick up the original definition of mixR:::print.mixfitEM instead of the trace()-altered version: trace(mixR:::print.mixfitEM, quote({ mc$x <- x }), at = 7) mixR:::print.mixfitEM(fit1) # works as expected, but that doesn't matter print(fit1) # tracer not called -- Best regards, Ivan __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see 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.
Re: [R] environments: functions within functions
On 25/05/2023 10:18 a.m., Sarah Goslee wrote: Hi, I ran into a problem with S3 method dispatch and scoping while trying to use functions from the mixR package within my own functions. I know enough to find the problem (I think!), but not enough to fix it myself. The problem isn't really a package-specific problem, so I'm starting here, and will file an issue with the maintainer once I have a solution. Detailed explanation below, but briefly, the S3 methods in this package use match.call() and then eval() to select the correct internal method. This works fine from the command line, but if the method is called from within another function, the use of environment() within eval() means that the objects passed to the wrapper function are no longer visible within the eval() call. I have a two-part question: A. How do I get around this right now? B. What would the correct approach be for the package authors? I'll try B first. The problem is that they want to look up fun.name in the environment that is visible from print.mixfitEM(), i.e. the mixR internal namespace environment, and they also want to evaluate that function the way it was evaluated when print.mixfitEM was called, i.e. in parent.frame(). R doesn't support that kind of thing in one step, so they should do it in two steps, e.g. rewriting print.mixfitEM something like this: function (x, digits = getOption("digits"), ...) { family <- x$family mc <- match.call() mc$digits <- digits fun.name <- paste0("print", family) e <- new.env(parent = parent.frame()) e[[fun.name]] <- get(fun.name) mc[[1]] <- as.name(fun.name) eval(mc, e) } This tries to get the function ("printnormal") from the local evaluation environment, but there's nothing there named "printnormal", so it goes to the parent environment, and gets it there. It puts it in a new environment whose parent is parent.frame() and everything works. For part A of your question, I can't think of any workaround other than using x as the name of the variable that is passed to print(). You could hide that fact by making a local function to do it, e.g. myprint <- function(x) print(x) and then calling myprint(fit1). Duncan Murdoch library(mixR) # first example from ?mixfit ## fitting the normal mixture models set.seed(103) x <- rmixnormal(200, c(0.3, 0.7), c(2, 5), c(1, 1)) data <- bin(x, seq(-1, 8, 0.25)) fit1 <- mixfit(x, ncomp = 2) # raw data rm(x, data) ### # simple function funworks <- function(x) { print(x) } ### # almost identical simple function funfails <- function(thisx) { print(thisx) } ### funworks(fit1) funfails(fit1) ### The explanation as I understand it... print called on this object gets passed to print.mixfitEM(), which is: function (x, digits = getOption("digits"), ...) { family <- x$family mc <- match.call() mc$digits <- digits fun.name <- paste0("print", family) mc[[1]] <- as.name(fun.name) eval(mc, environment()) } Working through the calls, when eval() is called from within funfails(), mc is printnormal(x = thisx, digits = 7) and the calling environment does not contain thisx. In funworks(), it's printnormal(x = x, digits = 7) and x is found. So, I can get around the problem by naming my argument x, as in funworks(), but that's unsatisfying. Is there something else I can do to get my functions to work? And what's the correct way to do what print.mixfitEM() is doing, so that it works regardless? I poked around for a while, but didn't find a clear (to me!) answer. Thanks, Sarah __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see 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.
[R] environments: functions within functions
Hi, I ran into a problem with S3 method dispatch and scoping while trying to use functions from the mixR package within my own functions. I know enough to find the problem (I think!), but not enough to fix it myself. The problem isn't really a package-specific problem, so I'm starting here, and will file an issue with the maintainer once I have a solution. Detailed explanation below, but briefly, the S3 methods in this package use match.call() and then eval() to select the correct internal method. This works fine from the command line, but if the method is called from within another function, the use of environment() within eval() means that the objects passed to the wrapper function are no longer visible within the eval() call. I have a two-part question: A. How do I get around this right now? B. What would the correct approach be for the package authors? library(mixR) # first example from ?mixfit ## fitting the normal mixture models set.seed(103) x <- rmixnormal(200, c(0.3, 0.7), c(2, 5), c(1, 1)) data <- bin(x, seq(-1, 8, 0.25)) fit1 <- mixfit(x, ncomp = 2) # raw data rm(x, data) ### # simple function funworks <- function(x) { print(x) } ### # almost identical simple function funfails <- function(thisx) { print(thisx) } ### funworks(fit1) funfails(fit1) ### The explanation as I understand it... print called on this object gets passed to print.mixfitEM(), which is: function (x, digits = getOption("digits"), ...) { family <- x$family mc <- match.call() mc$digits <- digits fun.name <- paste0("print", family) mc[[1]] <- as.name(fun.name) eval(mc, environment()) } Working through the calls, when eval() is called from within funfails(), mc is printnormal(x = thisx, digits = 7) and the calling environment does not contain thisx. In funworks(), it's printnormal(x = x, digits = 7) and x is found. So, I can get around the problem by naming my argument x, as in funworks(), but that's unsatisfying. Is there something else I can do to get my functions to work? And what's the correct way to do what print.mixfitEM() is doing, so that it works regardless? I poked around for a while, but didn't find a clear (to me!) answer. Thanks, Sarah -- Sarah Goslee (she/her) http://www.numberwright.com __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see 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.
[R] [Rd] R 4.3.1 scheduled for June 16
Full schedule available on developer.r-project.org in a short while. -- Peter Dalgaard, Professor, Center for Statistics, Copenhagen Business School Solbjerg Plads 3, 2000 Frederiksberg, Denmark Phone: (+45)38153501 Office: A 4.23 Email: pd@cbs.dk Priv: pda...@gmail.com ___ r-annou...@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-announce __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see 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.
Re: [R] data.frame with a column containing an array
So is this an expected behavior or is it a bug which should be reported somewhere else? Thanks! Georg Gesendet: Dienstag, 09. Mai 2023 um 19:28 Uhr Von: "Bert Gunter" An: "Georg Kindermann" Cc: "Rui Barradas" , r-help@r-project.org Betreff: Re: [R] data.frame with a column containing an array I think the following may provide a clearer explanation: subs <- c(1,3) DFA <- data.frame(id = 1:3) ar <- array(1:12, c(3,2,2)) ## yielding > ar , , 1 [,1] [,2] [1,] 1 4 [2,] 2 5 [3,] 3 6 , , 2 [,1] [,2] [1,] 7 10 [2,] 8 11 [3,] 9 12 ## array subscripting gives > ar[subs,,] , , 1 [,1] [,2] [1,] 1 4 [2,] 3 6 , , 2 [,1] [,2] [1,] 7 10 [2,] 9 12 ## Now with df's > DFA[["ar"]] <- ar > > DFM <- data.frame(id = 1:3) > DFM[["M"]] <- matrix(1:6, nc =2) > > str(DFM) 'data.frame': 3 obs. of 2 variables: $ id: int 1 2 3 $ M : int [1:3, 1:2] 1 2 3 4 5 6 > str(DFA) 'data.frame': 3 obs. of 2 variables: $ id: int 1 2 3 $ ar: int [1:3, 1:2, 1:2] 1 2 3 4 5 6 7 8 9 10 ... > > ## But the data frame print method for these give > DFM id M.1 M.2 1 1 1 4 2 2 2 5 3 3 3 6 > DFA id ar.1 ar.2 ar.3 ar.4 1 1 1 4 7 10 2 2 2 5 8 11 3 3 3 6 9 12 > > ## [.data.frame subscripting gives > DFA[subs,] id ar 1 1 1 3 3 3 > DFM[subs,] id M.1 M.2 1 1 1 4 3 3 3 6 > > ## but explicit array subscripting of course works > DFA$ar[match(subs,DFA$id),,] , , 1 [,1] [,2] [1,] 1 4 [2,] 3 6 , , 2 [,1] [,2] [1,] 7 10 [2,] 9 12 Cheers, Bert __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see 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.