Variable variable names



I have two variables, $ u \in \{0,40\}$ and $\gamma \in \{0,1\}$. I take $10$ values of $u$ and $5$ values of $\gamma$ and using their combinations as a pair of input parameters, I perform some mathematical operations a total of $10*5 =50$ times.

Now, say for $u=40$ and $\gamma=0.5$, I performed my mathematical operations and generated a $120 \text{x}9$ matrix of data. I would like to be able to call this Matrix, $\mathrm{DataU40G5}$ so I can keep track of where the data came from.


"Data" <> "U" <> ToString[Evaluate[u]] <> "G" <> ToString[Evaluate[gamma]]

creates a string that looks like $\mathrm{DataU40G5}$ but I am unable to use it as a variable name and feed data into it. How would I go about this?

Also, as I write this, I'm thinking that instead of doing all this, I can simply add the variables $u$ and $\gamma$ as columns to my records and have just one $(120*50)\text{x}(9+2)$ dimensional Matrix as my dataset.

Is this a better Idea? Even if it is, please answer the first question just so I can learn how to do that.


Posted 2012-08-31T23:43:23.920

Reputation: 6 498


See this question:

– rm -rf – 2012-08-31T23:50:52.787

Thanks R.M. I had seen that before posting but it seemed very complicated and tied to the complicated formulation of that question. I was hoping that my simpler problem would have a simpler answer. I will go read that thread and figure it out now. Thanks. – Amatya – 2012-09-01T00:14:24.940

Hmm, that answer is probably not useful here. Try looking into the documentation for ToExpression. That will allow you to convert your string to an expression. So if you build your entire string out, you can simply use ToExpression. Now note that this is almost never a good way to go about it (i.e., building complex strings and converting to expressions). The opportunities for bugs are high and its flexibility and possibilities for extensions are low. The right approach is to think of better data structures to handle the problem, but that's not the question here. – rm -rf – 2012-09-01T00:22:09.830



This is more a suggestion than a direct answer to your question.

Although sometimes it is useful to do what you are asking for, that is not the usual case.

It is much more common to use this kind of construct:

u = 40;  (*your var*)
g = 0.5; (*your other var*)

data[u, g] = RandomReal[u g, {9, 120}]; (*your calculated 120 x 9 matrix*)

(* Now use it this way*)
GraphicsRow[{MatrixPlot  [MeanFilter[data[40, .5], 2],  FrameTicks -> False], 
             ListLinePlot[MovingAverage[data[40, .5][[1]], 30]]}, Frame -> All]

Mathematica graphics

ListPlot3D[MedianFilter[data[40, .5], 2]]

Mathematica graphics

You can use it as a Matrix (because it IS a matrix), and perform vector operations:

ListLinePlot[data[40, .5].Range[120]]

Mathematica graphics

Dr. belisarius

Posted 2012-08-31T23:43:23.920

Reputation: 112 848

Oh man Verde! This is exactly what I wanted to be able to do, to be able manipulate, plot, run math operations on, process data across different parameter values. Storing my data as a function of the parameter values is absolutely the best thing to do. Thanks you!! – Amatya – 2012-09-02T18:35:48.150


Couple things here:

  1. R.M's suggestion of ToExpression is what you need here.
  2. Since your gamma variable contains a decimal, Mathematica treats it as a machine number and the decimal will stick around if you try to make it a string. This will result in a Protected Times error.

For the "mathematical operations", I'll just multiply U and gamma to give an example.

u = 40;
gamma = 0.5;
 "data" <> "U" <> ToString[u] <> "G" <> 
  StringReplace[ToString[gamma], "0." -> ""] <> "= gamma*u"]

I replace the "0." with nothing to get rid of that pesky decimal.

(*dataU40G5 = 20.*)


Posted 2012-08-31T23:43:23.920

Reputation: 10 290


A good solution to what you want is, IMHO, to simply store your data in a function that is indexed with the name you want to give to that data collection.

About generating the name string: your code contains two superfluous Evaluate-s.

So, the code now becomes:

(* First data set *)
u = 40;
g = 0.5;
name1 = "Data" <> "U" <> ToString[u] <> "G" <> ToString[g];

dataStore[name1] =  RandomReal[u g, {3, 4}]; (* Insert your function here*)

(* Second data set *)    
u = 10;
g = 2;
name2 = "Data" <> "U" <> ToString[u] <> "G" <> ToString[g];

dataStore[name2] = RandomReal[u g, {3, 4}];







Mathematica graphics

You could also define a function dataStore[] (without arguments) like this:

dataStore[] := Cases[DownValues[dataStore], _String, Infinity]

so that you, after a session in which data has been generated for various (and I gather unpredictable) values of u and g, you know what data sets are in store:


{"DataU10G2", "DataU40G0.5"}

Sjoerd C. de Vries

Posted 2012-08-31T23:43:23.920

Reputation: 63 549

Very nice implementation. – kale – 2012-09-01T15:08:44.770

Hey Sjoerd,Thanks, this is great! Your and Verde's suggestions are just what I was looking for! – Amatya – 2012-09-02T18:37:09.413