Select an existing variable by using readline - r

I'd like to allow the user of my script to pick an existing object (a vector).
I thought something like this
...
message("Select a vector of y values")
nwd <- readLines(n = 1)
return(mean(nwd))
...
but the result is NA because nwd is seen as a character.
How can I solve?
Thanks.

A bit safer than eval(parse(...)):
x <- 1:10
message("Select a vector of y values")
nwd <- readLines(n = 1)
#input x
mean(get(nwd))
#[1] 5.5

Related

How to use character as variable name in arguments? [R]

I am wondering how to tell R the string I used in the arguments of a function stands for a variable instead of the string itself. Specifically, I am dealing with 'Dict' package and run the following code as a trial.
library(Dict)
x = c(1,2)
d = dict(x = 1)
d$keys
# 'x'
What I want is c(1,2) to be the key instead of 'x'. The same problem goes for 'list', for example
y = 'happy'
l = list(y = 1)
names(l)
The result would be 'y'. Moreover, one can solve this situation by
names(l) <- y, but I don't think this is very efficient and clean.
Anyone has any idea how to do this in a one-line code? Thanks!
We could use setNames
out <- do.call(dict, setNames(rep(list(1), length(x)), x))
out$keys
[1] "1" "2"
Or we may use invoke or exec
library(purrr)
out <- invoke(dict, setNames(rep(1, length(x)), x))
out <- exec(dict, !!!setNames(rep(1, length(x)), x))
For the second case, also setNames works
setNames(list(1), y)
$happy
[1] 1
or we can use dplyr::lst
dplyr::lst(!! y := 1)
$happy
[1] 1

Vectors with sigma notation (R)

I'm now learning R and have some difficulties while computing sigma notation. I know how to do the basic stuff like this:
summ <- 10:100
sum(summ^3 + 4 * summ^2)
But I don't know how to do the same operations with the values that differ from i (include not only i (ex: x and y)) or operations with two sigma notations in a row.
At the beginning I thought that it just requires to do the same as in the simple sigma notation with only i's
summ <- 1:10
sum((x^summ) / (y^summ))
But it shows an error that it is not a numeric argument.
Thank you in advance for your help.
For you second formula, you can define a function like below
f <- function(x,y,n) sum((x/y)**(1:n))
For you last formula, you can rewrite the expression as a product of two terms (you need a math transformation as the first step if you want to simplify the procedure), since i and j are independent
> sum((1:20)**2)*sum(1/(5+(1:10)**3))
[1] 886.0118
Otherwise, a straightforward translation from the formula could be using nested sapply
> sum(sapply(1:20,function(i) sapply(1:10, function(j) i**2/(5+j**3))))
[1] 886.0118
That's, basically, the answer to the first question with undefined variables x and y:
x <- readline(prompt = "Enter x: ")
y <- readline(prompt = "Enter y: ")
x <- as.integer(x)
y <- as.integer(y)
i = 1:10
answer <- sum((x^i) / (y^i))
answer

Convert a variable into a string in R

I have a simple question. Suppose that I have this code:
y <- x
name <- "x"
Where x could be any R object.
Is there an a way the variable name to automatically take the string x once I assign x to y ?
If I understand correctly, you want the value of x to be assigned to y, while the variable name itself to be assigned to name as a string. If so, then you can capture x as an unevaluated expression, then 1) evaluate it and store the result to y, and 2) deparse it and store the resulting string to name:
z <- quote(x) # z contains unevaluated expression `x`
y <- eval(z) # evaluates the expression, returning the value of x
name <- deparse(z) # returns the expression as a string
If the question is how to get the name of the variable that was assigned to y then one cannot do that perfectly but a heuristic would be to examine every variable and return the name (or names) of anything with matching value.
If the code you are using is within a function and you are looking for variables that are defined in that function then use e <- environment() in place of the line that defines e below.
# test data
# start a fresh R session
a <- 1
x <- 2
y <- x
e <- .GlobalEnv
setdiff(names(Filter(isTRUE, eapply(e, identical, y))), "y")
## [1] "x"
Note
If the question is how to get value value of x from its name then:
Use get:
# test input
x <- 3
name <- "x"
y <- get(name)
y
## [1] 3
This will also work if x is in the global environment:
y <- .GlobalEnv[[name]]
y
## [1] 3
Would that work for you? I personally would not use anything like this in my scripts, but it accomplishes what you need:
assign_and_save_name <- function(new_var, var, var_name){
var_value <- sapply(ls(envir = parent.frame()), get)[[var]]
assign(new_var, var_value, parent.frame())
assign(var_name, var, parent.frame())
}
x <- 3
assign_and_save_name('y', 'x', 'name_x')

R: Change Vector Output to Several Ranges

I am using Jenks Natural Breaks via the BAMMtools package to segment my data in RStudio Version 1.0.153. The output is a vector that shows where the natural breaks occur in my data set, as such:
[1] 14999 41689 58415 79454 110184 200746
I would like to take the output above and create the ranges inferred by the breaks. Ex: 14999-41689, 41690-58415, 58416-79454, 79455-110184, 110185-200746
Are there any functions that I can use in R Studio to accomplish this? Thank you in advance!
Input data
x <- c(14999, 41689, 58415, 79454, 110184, 200746)
If you want the ranges as characters you can do
y <- x; y[1] <- y[1] - 1 # First range given in question doesn't follow the pattern. Adjusting for that
paste(head(y, -1) + 1, tail(y, -1), sep = '-')
#[1] "14999-41689" "41690-58415" "58416-79454" "79455-110184" "110185-200746"
If you want a list of the actual sets of numbers in each range you can do
seqs <- Map(seq, head(y, -1) + 1, tail(y, -1))
You can definitely create your own function that produces the exact output you're looking for, but you can use the cut function that will give you something like this:
# example vector
x = c(14999, 41689, 58415, 79454, 110184, 200746)
# use the vector and its values as breaks
ranges = cut(x, x, dig.lab = 6)
# see the levels
levels(ranges)
#[1] "(14999,41689]" "(41689,58415]" "(58415,79454]" "(79454,110184]" "(110184,200746]"

Plotting like Excel

I had a vector like this :
x= c(0.542949849, 0.242292905, 0.163459552, 0.069668097, 0.042969073, 0.035829825)
and I want to plot (x[i], x[i+1]). Using Excel I got this :
How can I get this graphic in R ? I tried this :
for(i in 1:5){
plot(x[i], x[i+1])
par(new = TRUE)
}
but it doesn't give the excepted result
Here are two solutions.
The first uses base R only.
x <- c(0.542949849, 0.242292905, 0.163459552, 0.069668097, 0.042969073, 0.035829825)
plot(range(x), range(x), type = "n")
for(i in seq_along(x)[-length(x)]){
points(x[i], x[i+1])
}
The second uses package tsDyn.
tsDyn::autopairs(x, type = "points")
Try this:
plot(embed(rev(x), 2))
or
plot(embed(x, 2)[, 2:1])
You can get what you want but you have to add a few intermediate steps.
You need to put in a qualifier to force the array to be numeric. This is the equivalent of forcing the array to be an array of float values. Otherwise all you get is integer values in your array.
You need to redefine the sub-components of x to 2 new vectors. Vector 'a' has an index of elements from 1 to 5 of the x array. It appears on the x-axis. Vector 'b' has an index of elements from 2 to 6 of the x array. It appears on the y-axis. The first elements in vectors a and b index position 1 are equivalent to x[i],x[i+1] where i is 1.
You need to bind the 2 vectors together and then plot the result.
x <- as.numeric(c(0.542949849, 0.242292905, 0.163459552, 0.069668097, 0.042969073, 0.035829825))
a <- x[1:5]
b <- x[2:6]
c <- cbind(a,b)
plot(c)
and the result graph is as follows

Resources