An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-help/attachments/20120803/799cc846/attachment.pl>
Recursive function calls
11 messages · Bert Gunter, Rui Barradas, Hadley Wickham +2 more
"Recursively loop over an object" is a pretty meaningless phrase, since it depends entirely on the structure of the object. For example, a character vector is an object, and there is no need for any sort of recursion to do what you want for it. The following regex example trims trailing "spaces" (see ?regex for an exact definition). Adapt it to whatever structure you like, probably with apply type functions.
x <- c(" ab ","ab \t ","\t\t")
x
[1] " ab " "ab \t " "\t\t"
sub("[[:space:]]+$","",x)
[1] " ab" "ab" ""
But note also that (e.g. S3) methods and is.list or is.recursive may
be useful in a more general approach, something like (where deSpace(x)
is a function with the above sub() expression):
nospace <- function(x){
if(is.atomic(x))deSpace(x)
else lapply(x, function(y)Recall(y)) ##?Recall for recursion
}
Note that this is completely untested, probably fails miserably and
isn't what you want anyway, ...
;-)
Good luck!
Cheers,
Bert
On Fri, Aug 3, 2012 at 9:12 AM, Gene Leynes <gleynes at gmail.com> wrote:
My apologies, I know that this is not a new problem, but I'm not sure how
to find the answer
I want to recursively loop over an object and trim trailing white space.
When I use this function on a list of data.frame I get output like this:
[1] "c(\" many spaces \", \" many spaces \")" "c(\" many spaces
\", \" many spaces \")"
What should I do to recombine the results?
If anyone has a good way to search for this type of question, that would be
appreciated. I tried rseek.org with "recursive", but after wading though
all the rpart references I didn't find something that seemed to help with
this problem.
Thank you very much.
trim <- function(x) {
if(length(x)>1) sapply(x[1], trim)
gsub("^[[:space:]]+|[[:space:]]+$", "", x)
}
tempobj = ' many spaces '
tempvec = c(tempobj, tempobj)
templist = list(tempvec, tempvec)
tempdf = data.frame(x = tempvec, y = tempvec)
trim(tempobj)
trim(tempvec)
trim(templist)
trim(tempdf)
Thank you,
Gene Leynes
_____________________________________________ *Data Scientist* *Mobile: 312-498-7702 **http://www.linkedin.com/in/geneleynes * <http://goog_598053156>*http://geneorama.com/ <http://geneorama.com/%20>* [[alternative HTML version deleted]] ______________________________________________ R-help at r-project.org 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.
Bert Gunter Genentech Nonclinical Biostatistics Internal Contact Info: Phone: 467-7374 Website: http://pharmadevelopment.roche.com/index/pdb/pdb-functional-groups/pdb-biostatistics/pdb-ncb-home.htm
Hello,
This seems to work.
trim2 <- function(x) {
if(is.atomic(x))
gsub("^[[:space:]]+|[[:space:]]+$", "", x)
else
sapply(x, function(y) trim2(y))
}
# Tests
trim2(tempobj)
trim2(tempvec)
trim2(templist)
trim2(tempdf)
# Extra test
templistlist <- list(templist, list(tempobj, tempdf))
trim2(templistlist)
Note, however, that the df is not returned as a df:
> class(trim2(tempdf))
[1] "matrix"
Hope this helps,
Rui Barradas
Em 03-08-2012 17:12, Gene Leynes escreveu:
My apologies, I know that this is not a new problem, but I'm not sure how
to find the answer
I want to recursively loop over an object and trim trailing white space.
When I use this function on a list of data.frame I get output like this:
[1] "c(\" many spaces \", \" many spaces \")" "c(\" many spaces
\", \" many spaces \")"
What should I do to recombine the results?
If anyone has a good way to search for this type of question, that would be
appreciated. I tried rseek.org with "recursive", but after wading though
all the rpart references I didn't find something that seemed to help with
this problem.
Thank you very much.
trim <- function(x) {
if(length(x)>1) sapply(x[1], trim)
gsub("^[[:space:]]+|[[:space:]]+$", "", x)
}
tempobj = ' many spaces '
tempvec = c(tempobj, tempobj)
templist = list(tempvec, tempvec)
tempdf = data.frame(x = tempvec, y = tempvec)
trim(tempobj)
trim(tempvec)
trim(templist)
trim(tempdf)
Thank you,
Gene Leynes
_____________________________________________ *Data Scientist* *Mobile: 312-498-7702 **http://www.linkedin.com/in/geneleynes * <http://goog_598053156>*http://geneorama.com/ <http://geneorama.com/%20>* [[alternative HTML version deleted]] ______________________________________________ R-help at r-project.org 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.
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-help/attachments/20120803/aa6b6641/attachment.pl>
Note that this is a common enough case that Hadley provides for it with the str_trim() function in his stringr package. Best, Michael
On Fri, Aug 3, 2012 at 12:02 PM, Bert Gunter <gunter.berton at gene.com> wrote:
"Recursively loop over an object" is a pretty meaningless phrase, since it depends entirely on the structure of the object. For example, a character vector is an object, and there is no need for any sort of recursion to do what you want for it. The following regex example trims trailing "spaces" (see ?regex for an exact definition). Adapt it to whatever structure you like, probably with apply type functions.
x <- c(" ab ","ab \t ","\t\t")
x
[1] " ab " "ab \t " "\t\t"
sub("[[:space:]]+$","",x)
[1] " ab" "ab" ""
But note also that (e.g. S3) methods and is.list or is.recursive may
be useful in a more general approach, something like (where deSpace(x)
is a function with the above sub() expression):
nospace <- function(x){
if(is.atomic(x))deSpace(x)
else lapply(x, function(y)Recall(y)) ##?Recall for recursion
}
Note that this is completely untested, probably fails miserably and
isn't what you want anyway, ...
;-)
Good luck!
Cheers,
Bert
On Fri, Aug 3, 2012 at 9:12 AM, Gene Leynes <gleynes at gmail.com> wrote:
My apologies, I know that this is not a new problem, but I'm not sure how
to find the answer
I want to recursively loop over an object and trim trailing white space.
When I use this function on a list of data.frame I get output like this:
[1] "c(\" many spaces \", \" many spaces \")" "c(\" many spaces
\", \" many spaces \")"
What should I do to recombine the results?
If anyone has a good way to search for this type of question, that would be
appreciated. I tried rseek.org with "recursive", but after wading though
all the rpart references I didn't find something that seemed to help with
this problem.
Thank you very much.
trim <- function(x) {
if(length(x)>1) sapply(x[1], trim)
gsub("^[[:space:]]+|[[:space:]]+$", "", x)
}
tempobj = ' many spaces '
tempvec = c(tempobj, tempobj)
templist = list(tempvec, tempvec)
tempdf = data.frame(x = tempvec, y = tempvec)
trim(tempobj)
trim(tempvec)
trim(templist)
trim(tempdf)
Thank you,
Gene Leynes
_____________________________________________ *Data Scientist* *Mobile: 312-498-7702 **http://www.linkedin.com/in/geneleynes * <http://goog_598053156>*http://geneorama.com/ <http://geneorama.com/%20>* [[alternative HTML version deleted]] ______________________________________________ R-help at r-project.org 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.
-- Bert Gunter Genentech Nonclinical Biostatistics Internal Contact Info: Phone: 467-7374 Website: http://pharmadevelopment.roche.com/index/pdb/pdb-functional-groups/pdb-biostatistics/pdb-ncb-home.htm
______________________________________________ R-help at r-project.org 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.
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-help/attachments/20120803/305d5892/attachment.pl>
On Fri, Aug 3, 2012 at 12:19 PM, Rui Barradas <ruipbarradas at sapo.pt> wrote:
Hello,
This seems to work.
trim2 <- function(x) {
if(is.atomic(x))
gsub("^[[:space:]]+|[[:space:]]+$", "", x)
else
sapply(x, function(y) trim2(y))
}
Using sapply is a bit dangerous here. Compare:
trim2(list(c("a", "b"), c("c", "d")))
# [,1] [,2]
# [1,] "a" "c"
# [2,] "b" "d"
trim2(list(c("a", "b"), c("c", "d", "e")))
# [[1]]
# [1] "a" "b"
#
# [[2]]
# [1] "c" "d" "e"
which I think is rather undesirable behaviour. sapply is suitable for
interactive use, but you should never use it inside a function because
you don't know what sort of data structure you'll get back.
I think it's also a bit unsafe to accept any type of input - you're
generally better off being explicit. This leads to trim3:
trim3 <- function(x) {
if (is.character(x)) {
gsub("^[[:space:]]+|[[:space:]]+$", "", x)
} else if (is.list(x)) {
lapply(x, trim3)
} else {
warning("Invalid input: ", paste(class(x), sep = "/"))
x
}
}
trim2(list(c("a", "b"), c("c", "d")))
trim3(list(c("a", "b"), c("c", "d")))
But then the function isn't extensible for new types of input, which
suggests an S3 implementation:
trim4 <- function(x) UseMethod("trim4")
trim4.character <- function(x) gsub("^[[:space:]]+|[[:space:]]+$", "", x)
trim4.list <- function(x) lapply(x, trim4)
trim4.default <- function(x) {
warning("Invalid input")
x
}
Hadley
Assistant Professor / Dobelman Family Junior Chair Department of Statistics / Rice University http://had.co.nz/
On Fri, Aug 3, 2012 at 3:36 PM, Gene Leynes <gleynes at gmail.com> wrote:
Rui, Yes, that's exactly it, thanks!! I wouldn't have thought of the "is.atomic". I was going after a series of tests for dimension and is.list.
One other helpful function that I haven't seen anyone mention this far is ? rapply [= recursive apply] Best, Michael
It's nice that R keeps the base function list short enough that you can look at it, but it would be nice to have a few more convenience functions included, especially ones that mirror common functions, like "trim"
sum(sapply(search(), function(x) length(ls(x))))
[1] 2376 Over two thousand objects seems like rather a lot to me... Hadley
Assistant Professor / Dobelman Family Junior Chair Department of Statistics / Rice University http://had.co.nz/
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-help/attachments/20120803/aa765d38/attachment.pl>
On Fri, Aug 3, 2012 at 5:41 PM, Gene Leynes <gleynes at gmail.com> wrote:
Ah yes, good point.
this was easy enough to write, it doesn't lose dimensions, and there's no
unnecessary complexity... unless you're passing in data frames, in which
you'll have to recombine them.
trim = function(x) gsub("^[[:space:]]+|[[:space:]]+$", "", x)
trimmer = function(x){
if(is.list(x)){
rapply(x, trim, how='replace')
}else{
trim(x)
}
}
Possibly, though I suppose it's a matter of judgement, even more
straightforward to just make your input into a list and don't special
case:
trimmer <- function(x){rapply(list(x), function(x)
gsub("^[[:space:]]+|[[:space:]]+$", "", x), how = "replace")[[1]]}
Note the "[[1]]" to undo the list() call we added.
Best,
Michael
tempobj = ' many spaces ' tempvec = c(tempobj, tempobj) templist = list(tempvec, tempvec) tempdf = data.frame(x = tempvec, y = tempvec) trimmer(tempobj) trimmer(tempvec) trimmer(templist) trimmer(tempdf) Thank you, Gene Leynes
_____________________________________________ Data Scientist Mobile: 312-498-7702 http://www.linkedin.com/in/geneleynes http://geneorama.com/ On Fri, Aug 3, 2012 at 4:14 PM, R. Michael Weylandt <michael.weylandt at gmail.com> wrote: On Fri, Aug 3, 2012 at 3:36 PM, Gene Leynes <gleynes at gmail.com> wrote: Rui, Yes, that's exactly it, thanks!! I wouldn't have thought of the "is.atomic". I was going after a series of tests for dimension and is.list. One other helpful function that I haven't seen anyone mention this far is ? rapply [= recursive apply] Best, Michael