3
$\begingroup$

I want to make a list of plots and my functions are named C1, C2... Cn.

The command I wish to execute is:

Table[Plot[Cn[t], {t, 0, 1}], {n, 1,6}]]

which obviously doesn't work. How is the equivalent of the above done in Mathematica?

EDIT: Thanks for the answers. Here is what it looks like: enter image description here

$\endgroup$

5 Answers 5

10
$\begingroup$

You can also use ToExpression to join the index n to your base function name, C, as in the following example:

C1 = Sin[x];
C2 = Cos[x];
C3 = Tan[x];
Table[Plot[Evaluate[ToExpression["C" <> ToString@i]], {x, -π, π}], {i, 3}]

enter image description here

$\endgroup$
3
  • 3
    $\begingroup$ That evaluates ToExpression and ToString for each point in the plot. (Which is not the biggest performance hit ever, but still...) $\endgroup$ Feb 2, 2012 at 22:32
  • $\begingroup$ The performance is not a problem for now, since I only have a couple of graphs I want to use, only as a visual aid. Thanks! $\endgroup$
    – CHM
    Feb 3, 2012 at 0:26
  • $\begingroup$ @CHM Brett's right. I've edited my answer to add an Evaluate, so please note it. $\endgroup$
    – rm -rf
    Feb 3, 2012 at 5:31
9
$\begingroup$

How about something like:

Plot[#, {t, 0, 1}] & /@ 
 (ToExpression /@ 
   Table["C" <> ToString[n] <> "[t]", {n, 1, 4}])

Edit With a form closer to your original code:

Table[Plot[ToExpression["C" <> ToString[n] <> "[t]"], {t, 0, 1}],
 {n, 1, 4}]

For example, with:

C1[t_] := t
C2[t_] := t^2
C3[t_] := t^3
C4[t_] := t^4

Using either of the two solutions here gives:

Mathematica graphics

$\endgroup$
4
  • $\begingroup$ oooh! Beat you by 13 seconds! :) $\endgroup$
    – rm -rf
    Feb 2, 2012 at 21:16
  • $\begingroup$ Blast! And I thought I had this one in the bag! But mine has a shiny Map version, too. $\endgroup$
    – Eli Lansey
    Feb 2, 2012 at 21:17
  • $\begingroup$ How is the Map version shinier? Is it performance-wise? $\endgroup$
    – CHM
    Feb 3, 2012 at 0:30
  • $\begingroup$ I meant shiny in terms of "fancy-looking," but in retrospect, it is faster. Reason being, as @BrettChampion noted in @RM's solution, when the ToExpression command is included in the Plot function, it's evaluated at each plot point. In the Map scenario it's evaluated once, and then the function is evaluated. I tested on my home computer and the Table method is around 3 times slower than the Map method. $\endgroup$
    – Eli Lansey
    Feb 3, 2012 at 0:37
9
$\begingroup$

Alternatively, you may define indexed family of functions like c[1],...,c[n]. Indices do not have to be contiguous, as you can get them all from the symbol definition. So if you define

c[1] = Sin;
c[2] = Cos;
c[3][x_] := Cos[x]^2;

you can do the plotting by iterating the index

Table[Plot[c[i][x], {x, -Pi, Pi}], {i, 3}]

You can also iterate over all defined indices in a general way:

Plot[c[#][x], {x, -Pi, Pi}] & /@ 
   Union[SubValues[c][[All, 1, 1, 0, 1]], 
        DownValues[c][[All, 1, 1, 1]]]

You may also define a function to help with such an iteration, to hide the ugliness of index scavenging:

AllFunIndices[sym_Symbol] := 
  Union[SubValues[sym][[All, 1, 1, 0, 1]], 
       DownValues[sym][[All, 1, 1, 1]]];
SetAttributes[AllFunIndices, HoldAll]

and then the plotting code over indices becomes much more transparent

Plot[c[#][x], {x, -Pi, Pi}] & /@ AllFunIndices[c]
$\endgroup$
3
  • $\begingroup$ I wondered that no one else was actually giving the very important tip to not use those variable names in the first place, there are several drawbacks in doing so: It will always lead to complicated constructs with ToExpression that are cryptic, inefficient and will pose even larger problems with namespaces when e.g. used in a package or when given away i any form (notebooks and CDF-files will warn about unsave code, demonstrations site will not accept). And that's just what immediately crosses my mind... $\endgroup$ Feb 4, 2012 at 17:02
  • $\begingroup$ @AlbertRetey, agree completely. That something can be done does not mean it should. These "reflection" capabilities are indeed ugly, error prone and not without side effects. IMO, they should be limited to specialized use in packages, not general Mathematica code. $\endgroup$ Jan 21, 2015 at 18:48
  • $\begingroup$ I don't remember what I was thinking when making that comment, but I think I wasn't really meaning to make that comment to your answer but rather to the question. What you suggest is IMHO the best alternative. The problems I described are to expected whenever one needs to make use of ToExpression and ToString and I am quite sure that I meant to put that comment somewhere else. In your approach I only see a potential performance penalty when accessing DownValues and SubValues to find all known definitions, but that might not be a problem at all if you don't have too many... $\endgroup$ Jan 22, 2015 at 20:36
8
$\begingroup$

You could define your functions like this:

Subscript[s, 1][t_] = Sin[t];
Subscript[s, 2][t_] = Cos[t];

And then plot using:

Plot[Evaluate[Table[Subscript[s, n][x], {n, 2}]], {x, -Pi, Pi}]

Just overlooked: This will create one Plot with all plots in it. The way your code snippet is written it looks as if you try to get each graph in its own plot in which case you have to use

Table[Plot[Subscript[s, n][x], {x, -Pi, Pi}], {n, 2}]
$\endgroup$
1
  • $\begingroup$ I hadn't thought about using a single Plot for all the functions. Might help me. Will check :) $\endgroup$
    – CHM
    Feb 3, 2012 at 0:28
6
$\begingroup$

This is the perfect time to use With to handle the creation of the variable name. For instance,

C1[t_] := Tanh[t];
C2[t_] := Sinh[t];
C3[t_] := Cosh[t];
GraphicsRow@Table[
 With[{f = ToExpression["C" <> ToString[i]]}, 
   Plot[f[t], {t, -1, 1}]], 
 {i, 3}]

gives

tanh, sinh, cosh plotted from -1 to 1

By using With to create the function name outside of Plot it is only executed once, not for every point.

$\endgroup$
7
  • $\begingroup$ Fun. It is nice to see different answers to the same question, it helps get a feel of how Mathematica can handle the problem. $\endgroup$
    – CHM
    Feb 3, 2012 at 3:07
  • $\begingroup$ Nice use of With. That solves the speed issue. I imagine Table and Map probably have nearly the same efficiency using this approach, then. $\endgroup$
    – Eli Lansey
    Feb 3, 2012 at 14:17
  • $\begingroup$ @EliLansey that's an interesting question. I've often found Table to be the slow point of any code I write, but I have not noticed the same thing with Map. I'll have to look at that. $\endgroup$
    – rcollyer
    Feb 3, 2012 at 14:21
  • $\begingroup$ @rcollyer I've noticed that too, so I've become the "Map everything" lunatic in our lab. Then, one of my coworkers was doing some calculation with a Table and I suggested Map to speed it up, and it actually was much slower. So, when I'm writing code that I need to be fast, I obsessively check which one will be faster. Wish I knew why, though... Maybe I'll ask a question. $\endgroup$
    – Eli Lansey
    Feb 3, 2012 at 14:26
  • $\begingroup$ @EliLansey most functional languages employ the idea of immutability, i.e. a variables value cannot be changed. So, Map has to produce a new list the same size as the old list while leaving the old one intact. I think, if it is slow, that's the reason: list construction can be fairly slow on mma. That's why Table can have truly awful performance. $\endgroup$
    – rcollyer
    Feb 3, 2012 at 14:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.