Let's assume that I want to create 10 variables which would look like this:
x1 = 1;
x2 = 2;
x3 = 3;
x4 = 4;
.
.
xi = i;
This is a simplified version of what I'm intending to do. Basically I just want so save code lines by creating these variables in an automated way. Is there the possibility to construct a variable name in Matlab? The pattern in my example would be ["x", num2str(i)]. But I cant find a way to create a variable with that name.
You can do it with eval but you really should not
eval(['x', num2str(i), ' = ', num2str(i)]); %//Not recommended
Rather use a cell array:
x{i} = i
I also strongly advise using a cell array or a struct for such cases. I think it will even give you some performance boost.
If you really need to do so Dan told how to. But I would also like to point to the genvarname function. It will make sure your string is a valid variable name.
EDIT: genvarname is part of core matlab and not of the statistics toolbox
for k=1:10
assignin('base', ['x' num2str(k)], k)
end
Although it is long overdue, i justed wanted to add another answer.
the function genvarname is exactly for these cases
and if you use it with a tmp structure array you do not need the eval cmd
the example 4 from this link is how to do it http://www.mathworks.co.uk/help/matlab/ref/genvarname.html
for k = 1:5
t = clock;
pause(uint8(rand * 10));
v = genvarname('time_elapsed', who);
eval([v ' = etime(clock,t)'])
end
all the best
eyal
If anyone else is interested, the correct syntax from Dan's answer would be:
eval(['x', num2str(i), ' = ', num2str(i)]);
My question already contained the wrong syntax, so it's my fault.
I needed something like this since you cannot reference structs (or cell arrays I presume) from workspace in Simulink blocks if you want to be able to change them during the simulation.
Anyway, for me this worked best
assignin('base',['string' 'parts'],values);
Related
I have an ODE that uses many functions. I wish to export these "helper" functions so that I may graph them vs the independent variable of the ODE.
function dFfuncvecdW = ODE(W,Ffuncvec);
X = Ffuncvec(1);
y = Ffuncvec(2);
#lots of code
R = ... #R is a function of X,W and y.
#and a few other functions that are a function of X,W and y.
dXdW = ... #some formula
dydW = ... #some formula
dFfuncvecdW = [dXdW; dydW];
end
I call this function with:
Wspan = [0 8000.]
X0 = [0; 1.]
[W,X] = ode45(#ODE, Wspan, X0);
I can easily output X or W to an excel file:
xlswrite(filename,X,'Conversion','A1');
But I what I need is to save "R" and many other functions' values to an Excel file.
How do I do that?
I am still extremely new to Matlab. I usually use Polymath, but for this system of ODE's, Polymath cannot compute the answer within a reasonable amount of time.
EDIT1: The code I use was generated by Polymath. I used a basic version of my problem so that Polymath may excecute the program as it only gives the Matlab code once the Polymath code has succefully run. After the export, the complete set of equations were entered.
The easiest, and possibly fastest, way to handle this is to re-evaluate your functions after ode45 returns W and X. If the functions are vectorized it will be easy. Otherwise, just use a simple for loop that iterates from 1 to length(W).
Alternatively, you can use an output function to save your values on each iteration to a file, or a global, or, most efficiently, a sub-function (a.k.a. nested function) variable that shares scope with an outer function (see here, for example). See this answer of mine for an example of how to use an output function.
I found a rather quick and painless solution to my answer.
I merely appended a text file with code inside the ode function.
EDIT: I am unable to comment because I do have enough rep on this branch of SE.
My solution was add the following code:
fid = fopen('abc1.txt', 'at');
fprintf(fid, '%f\n', T);
fclose(fid);
right above
dYfuncvecdW = [dFAdW; dFBdW; dFCdW; dFDdW; dydW];
at the end of the ode function. This proved to be a temporary solution. I have opened another question about the output I recieved.
I am trying to produce the argument string for an anonymous function based on the number of input arguments without using for loops. For example, if N=3, then I want a string that reads
#(ax(1),ax(2),ax(3),ay(1),ay(2),ay(3))
I tried using repmat('ax',1,N) but I cannot figure out how to interleave the (i) index.
Any ideas?
Aside: Great answers so far, the above problem has been solved. To provide some intuition for those who are wondering why I want to do this: I need to construct a very large matrix anonymous function (a Jacobian) on the order of 3000x3000. I initially used the Matlab operations jacobian and matlabFunction to construct the anonymous function; however, this was quite slow. Instead, since the closed form of the derivative was quite simple, I decided to form the anonymous function directly. This was done by forming the symbolic Jacobian matrix, J, then appending it to the above #() string by using char(J{:})' and using eval to form the final anonymous function. This may not be the most elegant solution but I find it runs much faster than the jacobian/matlabFunction combination, especially for large N (additionally the structure of the new approach allows for the evaluation to be done in parallel).
EDIT: Just for completeness, the correct form of the argument string for the anonymous function should read
#(ax1,ax2,ax3,ay1,ay2,ay3)
to avoid a syntax error associated with indexing.
I suggest the following:
N = 3;
argumentString = [repmat('ax(%i),',1,N),repmat('ay(%i),',1,N)];
functionString = sprintf(['#(',argumentString(1:end-1),')'], 1:N, 1:N)
First, you create input masks for sprintf (e.g. 'ax(%i)'), which you then fill in with the appropriate numbers to create the function string.
Note: the syntax #(ax(1),...) will not actually work. More likely, you want to use either #()someFunction(ax(1),...), or you are trying to pass multiple input arguments to an existing function, in which case storing the inputs in a cell array and calling the function as fun(axCell{:}) would work.
A solution would be to use arrayfun:
sx = strjoin(arrayfun(#(x) ['ax(' num2str(x) ')'], 1:3, 'UniformOutput', false), ',');
sy = strjoin(arrayfun(#(x) ['ay(' num2str(x) ')'], 1:3, 'UniformOutput', false), ',');
s = ['#(' sx ',' sy ')'];
contains
'#(ax(1),ax(2),ax(3),ay(1),ay(2),ay(3))'
Best,
Try this:
N = 3;
sx = strcat('ax(', arrayfun(#num2str, 1:N, 'uniformoutput', 0), '),');
sy = strcat('ay(', arrayfun(#num2str, 1:N, 'uniformoutput', 0), '),');
str = [sx{:} sy{:}];
str = ['#(' str(1:end-1) ')']
I have a first structure like:
struct1.Vx.Value=10;
struct1.Vy.Value=2;
In a 2nd structure, I write operations as strings:
struct2.param1.map='sqrt(Vx^2+Vy^2)';
struct2.param2.map='Vx+Vy';
What is the most efficient way to set:
struct2.param1.value= [sqrt(10^2+2^2)=10.198]
struct2.param2.value= [10+2=12]
I found a solution using assignin and fieldnames on struct1 to create variables Vx=10 and Vy=2
then, I use eval() on struct2 to perform the operations.
Ok, it works but I don't like this solution reading what is said on eval()...
Is there a more efficient way to do what I want?
Thanks!
I manage to find a good solution, formating my data differently:
s.Vx = 10;
s.Vy = 2;
Map1 = 'sqrt( s.Vx^2+ s.Vy^2)';
FunctionMap1 = str2func( [#(s) Map1] );
And then I can evaluate my function handle simply with:
Value = FunctionMap1(s)
Given a number
n = 42
What is the best way to convert it into a string?
s = String(n)
or
s = ''+n
or any better suggestion?
String interpolation might be the most natural approach in CoffeeScript:
s = "#{n}" # Just `'' + n` in disguise.
That might leave people wondering what you're doing though.
I think the best way would be:
(10).toString()
// or
n = 11;
n.toString()
Edited to fix syntax error. 10.toString() works in the CoffeeScript simulator but it's better to be safe.
There is no solution that is more "natural" than the other. Both are explicit and the reader will understand what it does right away in both cases.
Concerning performance, from this test, the fastest is :
s = '' + n
The other method, String(n), is slower.
I am using R to parse a list of strings in the form:
original_string <- "variable_name=variable_value"
First, I extract the variable name and value from the original string and convert the value to numeric class.
parameter_value <- as.numeric("variable_value")
parameter_name <- "variable_name"
Then, I would like to assign the value to a variable with the same name as the parameter_name string.
variable_name <- parameter_value
What is/are the function(s) for doing this?
assign is what you are looking for.
assign("x", 5)
x
[1] 5
but buyer beware.
See R FAQ 7.21
http://cran.r-project.org/doc/FAQ/R-FAQ.html#How-can-I-turn-a-string-into-a-variable_003f
You can use do.call:
do.call("<-",list(parameter_name, parameter_value))
There is another simple solution found there:
http://www.r-bloggers.com/converting-a-string-to-a-variable-name-on-the-fly-and-vice-versa-in-r/
To convert a string to a variable:
x <- 42
eval(parse(text = "x"))
[1] 42
And the opposite:
x <- 42
deparse(substitute(x))
[1] "x"
The function you are looking for is get():
assign ("abc",5)
get("abc")
Confirming that the memory address is identical:
getabc <- get("abc")
pryr::address(abc) == pryr::address(getabc)
# [1] TRUE
Reference: R FAQ 7.21 How can I turn a string into a variable?
Use x=as.name("string"). You can use then use x to refer to the variable with name string.
I don't know, if it answers your question correctly.
strsplit to parse your input and, as Greg mentioned, assign to assign the variables.
original_string <- c("x=123", "y=456")
pairs <- strsplit(original_string, "=")
lapply(pairs, function(x) assign(x[1], as.numeric(x[2]), envir = globalenv()))
ls()
assign is good, but I have not found a function for referring back to the variable you've created in an automated script. (as.name seems to work the opposite way). More experienced coders will doubtless have a better solution, but this solution works and is slightly humorous perhaps, in that it gets R to write code for itself to execute.
Say I have just assigned value 5 to x (var.name <- "x"; assign(var.name, 5)) and I want to change the value to 6. If I am writing a script and don't know in advance what the variable name (var.name) will be (which seems to be the point of the assign function), I can't simply put x <- 6 because var.name might have been "y". So I do:
var.name <- "x"
#some other code...
assign(var.name, 5)
#some more code...
#write a script file (1 line in this case) that works with whatever variable name
write(paste0(var.name, " <- 6"), "tmp.R")
#source that script file
source("tmp.R")
#remove the script file for tidiness
file.remove("tmp.R")
x will be changed to 6, and if the variable name was anything other than "x", that variable will similarly have been changed to 6.
I was working with this a few days ago, and noticed that sometimes you will need to use the get() function to print the results of your variable.
ie :
varnames = c('jan', 'feb', 'march')
file_names = list_files('path to multiple csv files saved on drive')
assign(varnames[1], read.csv(file_names[1]) # This will assign the variable
From there, if you try to print the variable varnames[1], it returns 'jan'.
To work around this, you need to do
print(get(varnames[1]))
If you want to convert string to variable inside body of function, but you want to have variable global:
test <- function() {
do.call("<<-",list("vartest","xxx"))
}
test()
vartest
[1] "xxx"
Maybe I didn't understand your problem right, because of the simplicity of your example. To my understanding, you have a series of instructions stored in character vectors, and those instructions are very close to being properly formatted, except that you'd like to cast the right member to numeric.
If my understanding is right, I would like to propose a slightly different approach, that does not rely on splitting your original string, but directly evaluates your instruction (with a little improvement).
original_string <- "variable_name=\"10\"" # Your original instruction, but with an actual numeric on the right, stored as character.
library(magrittr) # Or library(tidyverse), but it seems a bit overkilled if the point is just to import pipe-stream operator
eval(parse(text=paste(eval(original_string), "%>% as.numeric")))
print(variable_name)
#[1] 10
Basically, what we are doing is that we 'improve' your instruction variable_name="10" so that it becomes variable_name="10" %>% as.numeric, which is an equivalent of variable_name=as.numeric("10") with magrittr pipe-stream syntax. Then we evaluate this expression within current environment.
Hope that helps someone who'd wander around here 8 years later ;-)
Other than assign, one other way to assign value to string named object is to access .GlobalEnv directly.
# Equivalent
assign('abc',3)
.GlobalEnv$'abc' = 3
Accessing .GlobalEnv gives some flexibility, and my use case was assigning values to a string-named list. For example,
.GlobalEnv$'x' = list()
.GlobalEnv$'x'[[2]] = 5 # works
var = 'x'
.GlobalEnv[[glue::glue('{var}')]][[2]] = 5 # programmatic names from glue()