I have a simulation model that takes parameters.
Instead of passing all parameters to a main function (which is complicated for the user since the dimensions of some of the parameters depend on themselves, e.g. if n=2, vec_n is length 2), I wanted an internal PARAMETERS object within the package, which all functions could access, and the users can change.
I made a package Test with two functions and an internal list INTERNAL=list(a=2) which is saved in sysdata.rda.
test_function<-function(b){
INTERNAL$a = b
print(INTERNAL)
second_function()
}
second_function<-function(){
print(INTERNAL$a)
}
However on loading the package, and running it I get the following output:
> test_function(5)
$a
[1] 5
[1] 2
Clearly, the object itself doesn't change outside the function.
I'd appreciate any help / advice in getting this to work.
INTERNAL$a = b creates a local copy of INTERNAL in your function, and modifies that. Since you want to modify the global copy, you could use
INTERNAL$a <<- b
but this is a bad idea, and probably wouldn't work in a package: you can't modify most values in a package after it is installed.
Alternatives to this are to make INTERNAL into an environment (which you can modify), or create a function that returns the values you want, e.g.
INTERNAL <- function(a = "default", b = "default") {
list(a = a, b = b)
}
INTERNAL(a = 2)
#> $a
#> [1] 2
#>
#> $b
#> [1] "default"
Created on 2021-04-19 by the reprex package (v1.0.0)
You can combine these two ideas:
INTERNAL <- local({
saved <- list(a = "default", b = "default")
function(...) {
saved <<- modifyList(saved, list(...))
saved
}
})
INTERNAL(a = 1)
#> $a
#> [1] 1
#>
#> $b
#> [1] "default"
INTERNAL(b = 2)
#> $a
#> [1] 1
#>
#> $b
#> [1] 2
INTERNAL(c = 3)
#> $a
#> [1] 1
#>
#> $b
#> [1] 2
#>
#> $c
#> [1] 3
Created on 2021-04-19 by the reprex package (v1.0.0)
Related
I create the following range:
x <- seq(0,22)
Now I want to get some expected poisson estimations:
for (val in x) {
vec[val]<-(dpois(val,6.298387))*124
}
I want also the estimation for val = 0
(dpois(0,6.298387))*124
However, the vector "vec" obtained previously starts at val = 1.
How can I force the loop to take also values = 0?
Since R is 1-indexed, there is no such thing as vec[0]. The first valid index of vec is vec[1], so you probably intended
x <- seq(0,22)
vec <- numeric()
for (val in x) {
vec[val + 1] <- dpois(val, 6.298387) * 124
}
vec
#> [1] 2.280694e-01 1.436469e+00 4.523719e+00 9.497378e+00 1.495454e+01
#> [6] 1.883790e+01 1.977473e+01 1.779270e+01 1.400816e+01 9.803203e+00
#> [11] 6.174437e+00 3.535363e+00 1.855590e+00 8.990174e-01 4.044542e-01
#> [16] 1.698273e-01 6.685238e-02 2.476836e-02 8.666707e-03 2.872962e-03
#> [21] 9.047512e-04 2.713559e-04 7.768656e-05
However, the loop is not necessary, since dpois is vectorized like many R functions. Therefore the above code simplifies to this one-liner:
dpois(0:22, 6.298387) * 124
#> [1] 2.280694e-01 1.436469e+00 4.523719e+00 9.497378e+00 1.495454e+01
#> [6] 1.883790e+01 1.977473e+01 1.779270e+01 1.400816e+01 9.803203e+00
#> [11] 6.174437e+00 3.535363e+00 1.855590e+00 8.990174e-01 4.044542e-01
#> [16] 1.698273e-01 6.685238e-02 2.476836e-02 8.666707e-03 2.872962e-03
#> [21] 9.047512e-04 2.713559e-04 7.768656e-05
Created on 2022-07-22 by the reprex package (v2.0.1)
I have a list of ggplot objects that I am using the print() function to display. When I do this in r markdown it adds ## $`item name` where "item name" is the name of the object in the list. It adds this before every ggplot object. How do I get rid of this?
you can use unname function to make the list printed as usual
a <- list(`one` = 2 , `two` = 3 , `three` = 4)
print(unname(a))
#> [[1]]
#> [1] 2
#>
#> [[2]]
#> [1] 3
#>
#> [[3]]
#> [1] 4
I want to replace the for loop with a foreach loop but I get an error "unexpected token in". Below you can see my code. Just to mention that all the f's are file names. Do you have any idea?
for (f in file) {
print(f)
analyze(f)
tmp <- res4
y <- rbind(y, tmp)
}
Here is a simple foreach loop using the sequential %do% operator.
Note that the first 2 values of vector file are the output of print.
library(foreach)
file <- c("/data/an_01h.dat", "/data/an_01h.dat")
foreach (f=file) %do% {
print(f)
}
#> [1] "/data/an_01h.dat"
#> [1] "/data/an_01h.dat"
#> [[1]]
#> [1] "/data/an_01h.dat"
#>
#> [[2]]
#> [1] "/data/an_01h.dat"
Created on 2022-04-21 by the reprex package (v2.0.1)
And a parallelized loop. The %dopar% operator is a parallelizable operator. This time print doesn't show its output, see this SO question on this.
library(foreach)
library(doParallel)
#> Loading required package: iterators
#> Loading required package: parallel
file <- c("/data/an_01h.dat", "/data/an_01h.dat")
ncores <- detectCores() - 1L
registerDoParallel(ncores) # use multicore, set to the number of our cores
foreach (f=file) %dopar% {
print(f)
}
#> [[1]]
#> [1] "/data/an_01h.dat"
#>
#> [[2]]
#> [1] "/data/an_01h.dat"
Created on 2022-04-21 by the reprex package (v2.0.1)
Take a simple nested list L:
L <- list(lev1 = list(lev2 = c("bit1","bit2")), other=list(yep=1))
L
#$lev1
#$lev1$lev2
#[1] "bit1" "bit2"
#
#
#$other
#$other$yep
#[1] 1
And a vector giving a series of depths for each part I want to select from L:
sel <- c("lev1","lev2")
The result I want when indexing is:
L[["lev1"]][["lev2"]]
#[1] "bit1" "bit2"
Which I can generalise using Reduce like so:
Reduce(`[[`, sel, init=L)
#[1] "bit1" "bit2"
Now, I want to extend this logic to do a replacement, like so:
L[["lev1"]][["lev2"]] <- "new val"
, but I am genuinely stumped as to how to generate the recursive [[ selection in a way that will allow me to then assign to it as well.
Why cant you just do
L[[sel]] <- "new val"
well if you want to do the long way then
You could still use Reduce with modifyList or you could use [[<-. Here is an example with modifyList:
modifyList(L,Reduce(function(x,y)setNames(list(x),y),rev(sel),init = "new val"))
$lev1
$lev1$lev2
[1] "new val"
$other
$other$yep
[1] 1
You could eval() and parse() by concatenating everything. I am not sure how generalized you could make it:
``` r
L <- list(lev1 = list(lev2 = c("bit1","bit2")), other=list(yep=1))
L
#> $lev1
#> $lev1$lev2
#> [1] "bit1" "bit2"
#>
#>
#> $other
#> $other$yep
#> [1] 1
sel <- c("lev1","lev2")
eval(parse(text = paste0('L', paste0('[["', sel, '"]]', collapse = ''), '<- "new val"')))
L
#> $lev1
#> $lev1$lev2
#> [1] "new val"
#>
#>
#> $other
#> $other$yep
#> [1] 1
Created on 2019-11-25 by the reprex package (v0.3.0)
I'm trying to execute a function that uses the names of passed parameters with purrr::pmap. Unlike purrr::map (see below), pmap doesn't preserve these names. The below MWE captures the issue:
print_names <- function(x) {
print(names(x))
}
namedVec <- c(nameA = "valueA")
purrr::map(list(namedVec), print_names)
# [1] "nameA"
# [[1]]
# [1] "nameA"
purrr::pmap(list(namedVec), print_names)
# NULL
# $nameA
# NULL
Note that, in pmap, the .l argument needs to be a list of listed arguments, but in your function call it's just a list:
print_names <- function(x) {
print(names(x))
}
namedVec <- c(nameA = "valueA")
purrr::map(list(namedVec), ~print_names(.))
#> [1] "nameA"
#> [[1]]
#> [1] "nameA"
purrr::pmap(list(list(namedVec)), print_names)
#> [1] "nameA"
#> [[1]]
#> [1] "nameA"
Created on 2018-10-07 by the reprex package (v0.2.1)