names of leaves of nested list in R - r

I want to check if two nested lists have the same names at the last level.
If unlist gave an option not to concatenate names this would be trivial. However, it looks like I need some function leaf.names():
X <- list(list(a = pi, b = list(alpha.c = 1:5, 7.12)), d = "a test")
leaf.names(X)
[1] "a" "alpha.c" "NA" "d"
I want to avoid any inelegant grepping if possible. I feel like there should be some easy way to do this with rapply or unlist...

leaf.names <- function(X) names(rlang::squash(X))
or
leaf.names <- function(X){
while(any(sapply(X, is.list))) X <- purrr::flatten(X)
names(X)
}
gives
leaf.names(X)
# [1] "a" "alpha.c" "" "d"

Related

How can I reverse the words in a string in R without using strsplit? [duplicate]

I'm trying to teach myself R and in doing some sample problems I came across the need to reverse a string.
Here's what I've tried so far but the paste operation doesn't seem to have any effect.
There must be something I'm not understanding about lists? (I also don't understand why I need the [[1]] after strsplit.)
test <- strsplit("greg", NULL)[[1]]
test
# [1] "g" "r" "e" "g"
test_rev <- rev(test)
test_rev
# [1] "g" "e" "r" "g"
paste(test_rev)
# [1] "g" "e" "r" "g"
From ?strsplit, a function that'll reverse every string in a vector of strings:
## a useful function: rev() for strings
strReverse <- function(x)
sapply(lapply(strsplit(x, NULL), rev), paste, collapse="")
strReverse(c("abc", "Statistics"))
# [1] "cba" "scitsitatS"
stringi has had this function for quite a long time:
stringi::stri_reverse("abcdef")
## [1] "fedcba"
Also note that it's vectorized:
stringi::stri_reverse(c("a", "ab", "abc"))
## [1] "a" "ba" "cba"
As #mplourde points out, you want the collapse argument:
paste(test_rev, collapse='')
Most commands in R are vectorized, but how exactly the command handles vectors depends on the command. paste will operate over multiple vectors, combining the ith element of each:
> paste(letters[1:5],letters[1:5])
[1] "a a" "b b" "c c" "d d" "e e"
collapse tells it to operate within a vector instead.
The following can be a useful way to reverse a vector of strings x, and is slightly faster (and more memory efficient) because it avoids generating a list (as in using strsplit):
x <- rep( paste( collapse="", LETTERS ), 100 )
str_rev <- function(x) {
sapply( x, function(xx) {
intToUtf8( rev( utf8ToInt( xx ) ) )
} )
}
str_rev(x)
If you know that you're going to be working with ASCII characters and speed matters, there is a fast C implementation for reversing a vector of strings built into Kmisc:
install.packages("Kmisc")
str_rev(x)
You can also use the IRanges package.
library(IRanges)
x <- "ATGCSDS"
reverse(x)
# [1] "SDSCGTA"
You can also use the Biostrings package.
library(Biostrings)
x <- "ATGCSDS"
reverse(x)
# [1] "SDSCGTA"
If your data is in a data.frame, you can use sqldf:
myStrings <- data.frame(forward = c("does", "this", "actually", "work"))
library(sqldf)
sqldf("select forward, reverse(forward) `reverse` from myStrings")
# forward reverse
# 1 does seod
# 2 this siht
# 3 actually yllautca
# 4 work krow
Here is a function that returns the whole reversed string, or optionally the reverse string keeping only the elements specified by index, counting backward from the last character.
revString = function(string, index = 1:nchar(string)){
paste(rev(unlist(strsplit(string, NULL)))[index], collapse = "")
}
First, define an easily recognizable string as an example:
(myString <- paste(letters, collapse = ""))
[1] "abcdefghijklmnopqrstuvwxyz"
Now try out the function revString with and without the index:
revString(myString)
[1] "zyxwvutsrqponmlkjihgfedcba"
revString(myString, 1:5)
[1] "zyxwv"
The easiest way to reverse string:
#reverse string----------------------------------------------------------------
revString <- function(text){
paste(rev(unlist(strsplit(text,NULL))),collapse="")
}
#example:
revString("abcdef")
You can do with rev() function as mentioned in a previous post.
`X <- "MyString"
RevX <- paste(rev(unlist(strsplit(X,NULL))),collapse="")
Output : "gnirtSyM"
Thanks,
Here's a solution with gsub. Although I agree that it's easier with strsplit and paste (as pointed out in the other answers), it may be interesting to see that it works with regular expressions too:
test <- "greg"
n <- nchar(test) # the number of characters in the string
gsub(paste(rep("(.)", n), collapse = ""),
paste("", seq(n, 1), sep = "\\", collapse = ""),
test)
# [1] "gerg"
##function to reverse the given word or sentence
reverse <- function(mystring){
n <- nchar(mystring)
revstring <- rep(NA, n)
b <- n:1
c <- rev(b)
for (i in 1:n) {
revstring[i] <- substr(mystring,c[(n+1)- i], b[i])
}
newrevstring <- paste(revstring, sep = "", collapse = "")
return (cat("your string =", mystring, "\n",
("reverse letters = "), revstring, "\n",
"reverse string =", newrevstring,"\n"))
}
Here is one more base-R solution:
# Define function
strrev <- function(x) {
nc <- nchar(x)
paste(substring(x, nc:1, nc:1), collapse = "")
}
# Example
strrev("Sore was I ere I saw Eros")
[1] "sorE was I ere I saw eroS"
Solution was inspired by these U. Auckland slides.
The following Code will take input from user and reverse the entire string-
revstring=function(s)
print(paste(rev(strsplit(s,"")[[1]]),collapse=""))
str=readline("Enter the string:")
revstring(str)
So apparently front-end JS developers get asked to do this (for interviews) in JS without using built-in reverse functions. It took me a few minutes, but I came up with:
string <- 'hello'
foo <- vector()
for (i in nchar(string):1) foo <- append(foo,unlist(strsplit(string,''))[i])
paste0(foo,collapse='')
Which all could be wrapped in a function...
What about higher-order functionals? Reduce?

Reorder each row from end to beginning in R [duplicate]

I'm trying to teach myself R and in doing some sample problems I came across the need to reverse a string.
Here's what I've tried so far but the paste operation doesn't seem to have any effect.
There must be something I'm not understanding about lists? (I also don't understand why I need the [[1]] after strsplit.)
test <- strsplit("greg", NULL)[[1]]
test
# [1] "g" "r" "e" "g"
test_rev <- rev(test)
test_rev
# [1] "g" "e" "r" "g"
paste(test_rev)
# [1] "g" "e" "r" "g"
From ?strsplit, a function that'll reverse every string in a vector of strings:
## a useful function: rev() for strings
strReverse <- function(x)
sapply(lapply(strsplit(x, NULL), rev), paste, collapse="")
strReverse(c("abc", "Statistics"))
# [1] "cba" "scitsitatS"
stringi has had this function for quite a long time:
stringi::stri_reverse("abcdef")
## [1] "fedcba"
Also note that it's vectorized:
stringi::stri_reverse(c("a", "ab", "abc"))
## [1] "a" "ba" "cba"
As #mplourde points out, you want the collapse argument:
paste(test_rev, collapse='')
Most commands in R are vectorized, but how exactly the command handles vectors depends on the command. paste will operate over multiple vectors, combining the ith element of each:
> paste(letters[1:5],letters[1:5])
[1] "a a" "b b" "c c" "d d" "e e"
collapse tells it to operate within a vector instead.
The following can be a useful way to reverse a vector of strings x, and is slightly faster (and more memory efficient) because it avoids generating a list (as in using strsplit):
x <- rep( paste( collapse="", LETTERS ), 100 )
str_rev <- function(x) {
sapply( x, function(xx) {
intToUtf8( rev( utf8ToInt( xx ) ) )
} )
}
str_rev(x)
If you know that you're going to be working with ASCII characters and speed matters, there is a fast C implementation for reversing a vector of strings built into Kmisc:
install.packages("Kmisc")
str_rev(x)
You can also use the IRanges package.
library(IRanges)
x <- "ATGCSDS"
reverse(x)
# [1] "SDSCGTA"
You can also use the Biostrings package.
library(Biostrings)
x <- "ATGCSDS"
reverse(x)
# [1] "SDSCGTA"
If your data is in a data.frame, you can use sqldf:
myStrings <- data.frame(forward = c("does", "this", "actually", "work"))
library(sqldf)
sqldf("select forward, reverse(forward) `reverse` from myStrings")
# forward reverse
# 1 does seod
# 2 this siht
# 3 actually yllautca
# 4 work krow
Here is a function that returns the whole reversed string, or optionally the reverse string keeping only the elements specified by index, counting backward from the last character.
revString = function(string, index = 1:nchar(string)){
paste(rev(unlist(strsplit(string, NULL)))[index], collapse = "")
}
First, define an easily recognizable string as an example:
(myString <- paste(letters, collapse = ""))
[1] "abcdefghijklmnopqrstuvwxyz"
Now try out the function revString with and without the index:
revString(myString)
[1] "zyxwvutsrqponmlkjihgfedcba"
revString(myString, 1:5)
[1] "zyxwv"
The easiest way to reverse string:
#reverse string----------------------------------------------------------------
revString <- function(text){
paste(rev(unlist(strsplit(text,NULL))),collapse="")
}
#example:
revString("abcdef")
You can do with rev() function as mentioned in a previous post.
`X <- "MyString"
RevX <- paste(rev(unlist(strsplit(X,NULL))),collapse="")
Output : "gnirtSyM"
Thanks,
Here's a solution with gsub. Although I agree that it's easier with strsplit and paste (as pointed out in the other answers), it may be interesting to see that it works with regular expressions too:
test <- "greg"
n <- nchar(test) # the number of characters in the string
gsub(paste(rep("(.)", n), collapse = ""),
paste("", seq(n, 1), sep = "\\", collapse = ""),
test)
# [1] "gerg"
##function to reverse the given word or sentence
reverse <- function(mystring){
n <- nchar(mystring)
revstring <- rep(NA, n)
b <- n:1
c <- rev(b)
for (i in 1:n) {
revstring[i] <- substr(mystring,c[(n+1)- i], b[i])
}
newrevstring <- paste(revstring, sep = "", collapse = "")
return (cat("your string =", mystring, "\n",
("reverse letters = "), revstring, "\n",
"reverse string =", newrevstring,"\n"))
}
Here is one more base-R solution:
# Define function
strrev <- function(x) {
nc <- nchar(x)
paste(substring(x, nc:1, nc:1), collapse = "")
}
# Example
strrev("Sore was I ere I saw Eros")
[1] "sorE was I ere I saw eroS"
Solution was inspired by these U. Auckland slides.
The following Code will take input from user and reverse the entire string-
revstring=function(s)
print(paste(rev(strsplit(s,"")[[1]]),collapse=""))
str=readline("Enter the string:")
revstring(str)
So apparently front-end JS developers get asked to do this (for interviews) in JS without using built-in reverse functions. It took me a few minutes, but I came up with:
string <- 'hello'
foo <- vector()
for (i in nchar(string):1) foo <- append(foo,unlist(strsplit(string,''))[i])
paste0(foo,collapse='')
Which all could be wrapped in a function...
What about higher-order functionals? Reduce?

How assign names for each list[[i]] in a huge list file

I have a very big list file.dput() function for two of them is as below :
> dput(mydata).....
`NA` = c("SHC2", "GRB2", "HRAS", "KRAS", "NRAS", "SHC3",
"MAPK1", "MAPK3", "MAP2K1", "MAP2K2", "RAF1", "SHC1", "SOS1",
"YWHAB", "CDK1"), `NA` = c("NUP50", "NUPL2", "PSIP1", "NUP35",
"NUP205", "NUP210", "NUP188", "NUP62", "SLC25A4", "SLC25A5",
"SLC25A6", "HMGA1", "NUP43", "KPNA1", "NUP88", "NUP54", "NUP133",
"NUP107", "RANBP2", "LOC645870", "TPR", "NUP37", "NUP85",
"NUP214", "AAAS", "SEH1L", "RAE1", "BANF1", "NUP155", "NUP93",
"NUPL1", "POM121", "NUP153"), ....
I'm also have a file including names, but I can't assign it,
names(mydata)<-list("a", "b")# clears former data and replaces with "a" and "b"
names(mydata)<-c("a", "b")
I have tried using names(mydata) but it dosen't do what I need. I think "N" should be the name which I dont know how to access it. right?
If yes what should I do? Regards**
I'm not sure what you are trying to do. If you want to name the elements of a list with the names from another file, here's how to do it:
x <- list (1,2,3,4,5)
y <- LETTERS [1:5]
names (x) <- y
Thanks
The problem was: I was using [[ ]] to recruit names but [] should be used for names:
x <- list (1,2,3,4,5)
y <- LETTERS [1:5]
names (x) <- y
> x[[1]]
[1] 1
> x[1]
$A
[1] 1
> x[2]
$B
[1] 2

Avoid for loop in string replacement?

I've got data, a character vector (eventually I'll collapse it, so I don't care if it stays a vector or if it's treated as a single string), a vector of patterns, and a vector of replacements. I want each pattern in the data to be replaced by its respective replacement. I got it done with a stringr and a for loop, but is there a more R-like way to do it?
require(stringr)
start_string <- sample(letters[1:10], 10)
my_pattern <- c("a", "b", "c", "z")
my_replacement <- c("[this was an a]", "[this was a b]", "[this was a c]", "[no z!]")
str_replace(start_string, pattern = my_pattern, replacement = my_replacement)
# bad lengths, doesn't work
str_replace(paste0(start_string, collapse = ""),
pattern = my_pattern, replacement = my_replacement)
# vector output, not what I want in this case
my_result <- start_string
for (i in 1:length(my_pattern)) {
my_result <- str_replace(my_result,
pattern = my_pattern[i], replacement = my_replacement[i])
}
> my_result
[1] "[this was a c]" "[this was an a]" "e" "g" "h" "[this was a b]"
[7] "d" "j" "f" "i"
# This is what I want, but is there a better way?
In my case, I know each pattern will occur at most once, but not every pattern will occur. I know I could use str_replace_all if patterns might occur more than once; I hope a solution would also provide that option. I'd also like a solution that uses my_pattern and my_replacement so that it could be part of a function with those vectors as arguments.
I'll bet there's another way to do this, but my first thought was gsubfn:
my_repl <- function(x){
switch(x,a = "[this was an a]",
b = "[this was a b]",
c = "[this was a c]",
z = "[this was a z]")
}
library(gsubfn)
start_string <- sample(letters[1:10], 10)
gsubfn("a|b|c|z",my_repl,x = start_string)
If the patterns you are search for a acceptably valid names for list elements, this will also work:
names(my_replacement) <- my_pattern
gsubfn("a|b|c|z",as.list(my_replacement),start_string)
Edit
But frankly, if I really had to do this a lot in my own code, I would probably just do the for loop thing, wrapped in a function. Here's a simple version using sub and gsub rather than the functions from stringr:
vsub <- function(pattern,replacement,x,all = TRUE,...){
FUN <- if (all) gsub else sub
for (i in seq_len(min(length(pattern),length(replacement)))){
x <- FUN(pattern = pattern[i],replacement = replacement[i],x,...)
}
x
}
vsub(my_pattern,my_replacement,start_string)
But of course, one of the reasons that there isn't a built-in function for this that's well known is probably that sequential replacements like this can't be pretty fragile, because they are so order dependent:
vsub(rev(my_pattern),rev(my_replacement),start_string)
[1] "i" "[this w[this was an a]s [this was an a] c]"
[3] "[this was an a]" "g"
[5] "j" "d"
[7] "f" "[this w[this was an a]s [this was an a] b]"
[9] "h" "e"
Here's an option based on gregrexpr, regmatches, and regmatches<-. Do be aware that there are limits to the length of regular expressions that can be matched, so this won't work if you try to match too many long patterns with it.
replaceSubstrings <- function(patterns, replacements, X) {
pat <- paste(patterns, collapse="|")
m <- gregexpr(pat, X)
regmatches(X, m) <-
lapply(regmatches(X,m),
function(XX) replacements[match(XX, patterns)])
X
}
## Try it out
patterns <- c("cat", "dog")
replacements <- c("tiger", "coyote")
sentences <- c("A cat", "Two dogs", "Raining cats and dogs")
replaceSubstrings(patterns, replacements, sentences)
## [1] "A tiger" "Two coyotes"
## [3] "Raining tigers and coyotes"

How to reverse a string in R

I'm trying to teach myself R and in doing some sample problems I came across the need to reverse a string.
Here's what I've tried so far but the paste operation doesn't seem to have any effect.
There must be something I'm not understanding about lists? (I also don't understand why I need the [[1]] after strsplit.)
test <- strsplit("greg", NULL)[[1]]
test
# [1] "g" "r" "e" "g"
test_rev <- rev(test)
test_rev
# [1] "g" "e" "r" "g"
paste(test_rev)
# [1] "g" "e" "r" "g"
From ?strsplit, a function that'll reverse every string in a vector of strings:
## a useful function: rev() for strings
strReverse <- function(x)
sapply(lapply(strsplit(x, NULL), rev), paste, collapse="")
strReverse(c("abc", "Statistics"))
# [1] "cba" "scitsitatS"
stringi has had this function for quite a long time:
stringi::stri_reverse("abcdef")
## [1] "fedcba"
Also note that it's vectorized:
stringi::stri_reverse(c("a", "ab", "abc"))
## [1] "a" "ba" "cba"
As #mplourde points out, you want the collapse argument:
paste(test_rev, collapse='')
Most commands in R are vectorized, but how exactly the command handles vectors depends on the command. paste will operate over multiple vectors, combining the ith element of each:
> paste(letters[1:5],letters[1:5])
[1] "a a" "b b" "c c" "d d" "e e"
collapse tells it to operate within a vector instead.
The following can be a useful way to reverse a vector of strings x, and is slightly faster (and more memory efficient) because it avoids generating a list (as in using strsplit):
x <- rep( paste( collapse="", LETTERS ), 100 )
str_rev <- function(x) {
sapply( x, function(xx) {
intToUtf8( rev( utf8ToInt( xx ) ) )
} )
}
str_rev(x)
If you know that you're going to be working with ASCII characters and speed matters, there is a fast C implementation for reversing a vector of strings built into Kmisc:
install.packages("Kmisc")
str_rev(x)
You can also use the IRanges package.
library(IRanges)
x <- "ATGCSDS"
reverse(x)
# [1] "SDSCGTA"
You can also use the Biostrings package.
library(Biostrings)
x <- "ATGCSDS"
reverse(x)
# [1] "SDSCGTA"
If your data is in a data.frame, you can use sqldf:
myStrings <- data.frame(forward = c("does", "this", "actually", "work"))
library(sqldf)
sqldf("select forward, reverse(forward) `reverse` from myStrings")
# forward reverse
# 1 does seod
# 2 this siht
# 3 actually yllautca
# 4 work krow
Here is a function that returns the whole reversed string, or optionally the reverse string keeping only the elements specified by index, counting backward from the last character.
revString = function(string, index = 1:nchar(string)){
paste(rev(unlist(strsplit(string, NULL)))[index], collapse = "")
}
First, define an easily recognizable string as an example:
(myString <- paste(letters, collapse = ""))
[1] "abcdefghijklmnopqrstuvwxyz"
Now try out the function revString with and without the index:
revString(myString)
[1] "zyxwvutsrqponmlkjihgfedcba"
revString(myString, 1:5)
[1] "zyxwv"
The easiest way to reverse string:
#reverse string----------------------------------------------------------------
revString <- function(text){
paste(rev(unlist(strsplit(text,NULL))),collapse="")
}
#example:
revString("abcdef")
You can do with rev() function as mentioned in a previous post.
`X <- "MyString"
RevX <- paste(rev(unlist(strsplit(X,NULL))),collapse="")
Output : "gnirtSyM"
Thanks,
Here's a solution with gsub. Although I agree that it's easier with strsplit and paste (as pointed out in the other answers), it may be interesting to see that it works with regular expressions too:
test <- "greg"
n <- nchar(test) # the number of characters in the string
gsub(paste(rep("(.)", n), collapse = ""),
paste("", seq(n, 1), sep = "\\", collapse = ""),
test)
# [1] "gerg"
##function to reverse the given word or sentence
reverse <- function(mystring){
n <- nchar(mystring)
revstring <- rep(NA, n)
b <- n:1
c <- rev(b)
for (i in 1:n) {
revstring[i] <- substr(mystring,c[(n+1)- i], b[i])
}
newrevstring <- paste(revstring, sep = "", collapse = "")
return (cat("your string =", mystring, "\n",
("reverse letters = "), revstring, "\n",
"reverse string =", newrevstring,"\n"))
}
Here is one more base-R solution:
# Define function
strrev <- function(x) {
nc <- nchar(x)
paste(substring(x, nc:1, nc:1), collapse = "")
}
# Example
strrev("Sore was I ere I saw Eros")
[1] "sorE was I ere I saw eroS"
Solution was inspired by these U. Auckland slides.
The following Code will take input from user and reverse the entire string-
revstring=function(s)
print(paste(rev(strsplit(s,"")[[1]]),collapse=""))
str=readline("Enter the string:")
revstring(str)
So apparently front-end JS developers get asked to do this (for interviews) in JS without using built-in reverse functions. It took me a few minutes, but I came up with:
string <- 'hello'
foo <- vector()
for (i in nchar(string):1) foo <- append(foo,unlist(strsplit(string,''))[i])
paste0(foo,collapse='')
Which all could be wrapped in a function...
What about higher-order functionals? Reduce?

Resources