How do I get the assigned numeric value of string in loop? - r

In the following code below I want to get the number for pattern[i] instead of pattern itself in get_number. Thanks
pattern <- c("Ago2_1","Ago2_2", "WT_1", "WT_2", "DCLd_1", "DCLd_2")
##STATS
Ago2_1 <- 299117512
Ago2_2 <- 29564885
DCLd_1 <- 67004254
DCLd_2 <- 77682528
WT_1 <- 27073135
WT_2 <- 113214012
for ( i in 1:length(pattern)){
get_number <- pattern [i]
}

You can use get(). In your for loop, i is one of the strings in pattern. Therefore, just use get() to retrieve its numeric value and store it somewhere (in this example, in a list).
pattern <- c("Ago2_1","Ago2_2", "WT_1", "WT_2", "DCLd_1", "DCLd_2")
##STATS
Ago2_1 <- 29911751
Ago2_2 <- 29564885
DCLd_1 <- 67004254
DCLd_2 <- 77682528
WT_1 <- 27073135
WT_2 <- 113214012
# initialize a collector
get_number <- list()
for ( i in pattern){
get_number[[(length(get_number) + 1)]] <- get(i)
}
get_number
[[1]]
[1] 29911751
[[2]]
[1] 29564885
[[3]]
[1] 27073135
[[4]]
[1] 113214012
[[5]]
[1] 67004254

We can use mget to return the values in a list
mget(pattern)
#$Ago2_1
#[1] 29911751
#$Ago2_2
#[1] 29564885
#$WT_1
#[1] 27073135
#$WT_2
#[1] 113214012
#$DCLd_1
#[1] 67004254
#$DCLd_2
#[1] 77682528

Related

Capture and evaluate function arguments within function body

I would like to capture a function's arguments within its body to help with logging. I have found that match.call() and sys.call() work when the argument value is explicitly stated in the function call, but don't output an evaluated value when an object name is used.
Here's a simplified example:
gauss_vector <- function(number) {
sys_args <- as.list(sys.call())
match_args <- as.list(match.call())
output <- rnorm(n = number)
list(sys_args,
match_args,
output)
}
When this function is called like this:
gauss_vector(number = 5)
The resulting list includes the value 5.
[[1]]
[[1]][[1]]
gauss_vector
[[1]]$number
[1] 5
[[2]]
[[2]][[1]]
gauss_vector
[[2]]$number
[1] 5
[[3]]
[1] 0.9663434 0.8051087 0.1576298 0.3189806 -2.3110680
However, when the function is called like this:
n <- 5
gauss_vector(number = n)
The resulting list only includes n.
[[1]]
[[1]][[1]]
gauss_vector
[[1]]$number
n
[[2]]
[[2]][[1]]
gauss_vector
[[2]]$number
n
[[3]]
[1] -0.6017670 -0.7631405 0.7793892 -0.7529637 1.3022802
Is there a way to capture the evaluated figure rather than the object name when the function is called in the second way?
You could eval all the arguments passed to the function.
gauss_vector <- function(number) {
sys_args <- as.list(sys.call())
sys_args[-1] <- lapply(sys_args[-1], eval)
match_args <- as.list(match.call())
match_args[-1] <- lapply(match_args[-1], eval)
output <- rnorm(n = number)
list(sys_args,match_args,output)
}
gauss_vector(n)
#[[1]]
#[[1]][[1]]
#gauss_vector
#[[1]][[2]]
#[1] 5
#[[2]]
#[[2]][[1]]
#gauss_vector
#[[2]]$number
#[1] 5
#[[3]]
#[1] 0.6998265 0.4037748 1.8558809 -0.1343624 -1.5600925

How to convert object variable into string inside a function

I have the following list of vectors
v1 <- c("foo","bar")
v2 <- c("qux","uip","lsi")
mylist <- list(v1,v2)
mylist
#> [[1]]
#> [1] "foo" "bar"
#>
#> [[2]]
#> [1] "qux" "uip" "lsi"
What I want to do is to apply a function so that it prints the this string:
v1:foo,bar
v2:qux,uip,lsi
So it involves two step: 1) Convert object variable to string and
2) make the vector into string. The latter is easy as I can do this:
make_string <- function (content_vector) {
cat(content_vector,sep=",")
}
make_string(mylist[[1]])
# foo,bar
make_string(mylist[[2]])
# qux,uip,lsi
I am aware of this solution, but I don't know how can I turn the object name into a string within a function so that
it prints like my desired output.
I need to to this inside a function, because there are many other output I need to process.
We can use
cat(paste(c('v1', 'v2'), sapply(mylist, toString), sep=":", collapse="\n"), '\n')
#v1:foo, bar
#v2:qux, uip, lsi
If we need to pass the original object i.e. 'v1', 'v2'
make_string <- function(vec){
obj <- deparse(substitute(vec))
paste(obj, toString(vec), sep=":")
}
make_string(v1)
#[1] "v1:foo, bar"
If you want to use a list, you can name the objects in the list to be able to use them in a function. Remove the cat if you just want a string to be returned.
v1 <- c("foo","bar")
v2 <- c("qux","uip","lsi")
# objects given names here
mylist <- list("v1" = v1, "v2" = v2)
# see names now next to the $
mylist
$v1
[1] "foo" "bar"
$v2
[1] "qux" "uip" "lsi"
make_string <- function (content_vector) {
vecname <- names(content_vector)
cat(paste0(vecname, ":", paste(sapply(content_vector, toString), sep = ",")))
}
make_string(mylist[1])
v1:foo, bar
make_string(mylist[2])
v2:qux, uip, lsi

How to extract parts from a string

I have an string called PATTERN:
PATTERN <- "MODEL_Name.model-OUTCOME_any.outcome-IMP_number"
and I would like to parse the string using a pattern matching function, like grep, sub, ... to obtain a string variable MODEL equal to "Name.model", a string variable OUTCOME equal to "any.outcome" and an integer variable IMP equal to number.
If MODEL, OUTCOME and IMP were all integers, I could get the values using function sub:
PATTERN <- "MODEL_002-OUTCOME_007-IMP_001"
pattern_build <- "MODEL_([0-9]+)-OUTCOME_([0-9]+)-IMP_([0-9]+)"
MODEL <- as.integer(sub(pattern_build, "\\1", PATTERN))
OUTCOME <- as.integer(sub(pattern_build, "\\2", PATTERN))
IMP <- as.integer(sub(pattern_build, "\\3", PATTERN))
Do you have any idea of how to match the string contained in variable PATTERN?
Possible tricky patterns are:
PATTERN <- "MODEL_PS2-OUTCOME_stroke_i-IMP_001"
PATTERN <- "MODEL_linear-model-OUTCOME_stroke_i-IMP_001"
A solution which is also able to deal with the 'tricky' patterns:
PATTERN <- "MODEL_linear-model-OUTCOME_stroke_i-IMP_001"
lst <- strsplit(PATTERN, '([A-Z]+_)')[[1]][2:4]
lst <- sub('-$','',lst)
which gives:
> lst
[1] "linear-model" "stroke_i" "001"
And if you want that in a dataframe:
df <- as.data.frame.list(lst)
names(df) <- c('MODEL','OUTCOME','IMP')
which gives:
> df
MODEL OUTCOME IMP
1 linear-model stroke_i 001
A minimal-regex approach,
sapply(strsplit(PATTERN, '-'), function(i) sub('(.*?_){1}', '', i))
# [,1]
#[1,] "PS2"
#[2,] "stroke_i"
#[3,] "001"
You may use a pattern with capturing groups matching any chars, as few as possible between known delimiting substrings:
MODEL_(.*?)-OUTCOME_(.*?)-IMP_(.*)
See the regex demo. Note that the last .* is greedy since you get all the rest of the string into this capture.
You may precise this pattern to only allow matching expected characters (say, to match digits into the last capturing group, use ([0-9]+) rather than (.*).
Use it with, say, str_match from stringr:
> library(stringr)
> x <- "MODEL_Name.model-OUTCOME_any.outcome-IMP_number"
> res <- str_match(x, "MODEL_(.*?)-OUTCOME_(.*?)-IMP_(.*)")
> res[,2]
[1] "Name.model"
> res[,3]
[1] "any.outcome"
> res[,4]
[1] "number"
>
A base R solution using the same regex will involve a regmatches / regexec:
> res <- regmatches(x, regexec("MODEL_(.*?)-OUTCOME_(.*?)-IMP_(.*)", x))[[1]]
> res[2]
[1] "Name.model"
> res[3]
[1] "any.outcome"
> res[4]
[1] "number"
>

Merging specific specific strings in character vector

I have character vector where each level is a word. It has been generated from a text in which some segments are marked up with angular brackets. These segments vary in length. I need the marked up segments to be merged in the vector.
The input looks like this:
c("This","is","some","text","with","<marked","up","chunks>[L]","in","it")
I need the output to look like this:
c("This","is","some","text","with","<marked up chunks>[L]","in","it")
Thanks.
Here's an approach that also works with multiple chunks in a vector:
vec <- c("This","is","some","text","with","<marked","up","chunks>[L]","in","it")
from <- grep("<", vec)
to <- grep(">", vec)
idx <- mapply(seq, from, to, SIMPLIFY = FALSE)
new_strings <- sapply(idx, function(x)
paste(vec[x], collapse = " "))
replacement <- unlist(mapply(function(x, y) c(y, rep(NA, length(x) - 1)),
idx, new_strings, SIMPLIFY = FALSE))
new_vec <- "attributes<-"(na.omit(replace(vec, unlist(idx), replacement)), NULL)
[1] "This" "is"
[3] "some" "text"
[5] "with" "<marked up chunks>[L]"
[7] "in" "it"

Using do.call to call a list of functions

I am having trouble figuring out how to use do.call to call and run a list of functions.
for example:
make.draw = function(i){i;function()runif(i)}
function.list = list()
for (i in 1:3) function.list[[i]] = make.draw(i)
will result in
> function.list[[1]]()
[1] 0.2996515
> function.list[[2]]()
[1] 0.7276203 0.4704813
> function.list[[3]]()
[1] 0.9092999 0.7307774 0.4647443
what I want to do is create a function that calls all three functions in the list at one go. from what I understand as.call() can be used to do this but I am having trouble connecting the dots and getting 6 uniform random draws from function.list.
Did you want something like this?
lapply(function.list, do.call, list())
# [[1]]
# [1] 0.5777857
# [[2]]
# [1] 0.8970102 0.5892031
# [[3]]
# [1] 0.4712016 0.2624851 0.2353192
make.draw = function(i){runif(i)}
Map(make.draw, 1:3)
#[[1]]
#[1] 0.03442084
#[[2]]
#[1] 0.6899443 0.8896434
#[[3]]
#[1] 0.3899678 0.2845898 0.4920698

Resources