0
$\begingroup$

I have this code. The problem I have is with the % in the Manipulate (after Grid). If I replace % with data, then the values are not evaluated anymore? But how come? Isn't the % refering to data?

Clear["Global`*"]

PosH = (1 - pH) (1 - kans);
PosI = pI kans;
NegH = pH (1 - kans);
NegI = (1 - pI) kans;

{{PosH, PosI, PosH + PosI}, {NegH, NegI, NegH + NegI}, {PosH + NegH, 
   PosI + NegI, 1}};
Prepend[%, {"Gezond", "Ziek", ""}];
data = MapThread[Prepend, {%, {"", "Positief", "Negatief", ""}}];

Manipulate[
 AccountingForm[
  Grid[%, Frame -> All], {3, 3}], {kans}, {{kans, 0.0001}, 0, 
  1}, {{pI, 0.99}, 0, 1}, {{pH, 0.99}, 0, 1}]
$\endgroup$
  • $\begingroup$ You need to assign the list to data to the result of the two lines of code preceding the existing assignment to data. All three of those rows should be assigned to data not just the last row. Then you will be able to replace the %s with data. $\endgroup$ – Edmund Jul 2 '17 at 0:23
  • $\begingroup$ No, % refers to the output value of the output (whether or not the output was suppressed with a ;). It does not refer to data, but its value. Apparently Manipulate reads in the value of % before processing it to create its output. (I didn't know it would do this, but it makes sense to me.) $\endgroup$ – Michael E2 Jul 2 '17 at 0:23
2
$\begingroup$

There is a lot more wrong with your code than the misuse of %. The variables you define globally must be brought into the scope to the Manipulate expression. Here is one way to get all the variables properly scoped.

DynamicModule[{PosH, PosI, NegH, NegI, data, titles, rowLabels, gridData},
  Manipulate[
    AccountingForm[Grid[gridData, Frame -> All], {3, 3}],
    {{kans, 0.0001}, 0, 1, Appearance -> "Labeled"},
    {{pI, 0.99}, 0, 1, Appearance -> "Labeled"},
    {{pH, 0.99}, 0, 1, Appearance -> "Labeled"},
    Initialization :> (
      PosH := (1 - pH) (1 - kans);
      PosI := pI kans;
      NegH := pH (1 - kans);
      NegI := (1 - pI) kans;
      data :=
        {{PosH, PosI, PosH + PosI}, 
         {NegH, NegI, NegH + NegI}, 
         {PosH + NegH, PosI + NegI, 1}}; 
      titles = {"Gezond", "Ziek", ""}; 
      rowLabels = {"", "Positief", "Negatief", ""}; 
      gridData := 
        MapThread[Join[{#1}, #2] &, {rowLabels, Prepend[data, titles]}]),
      TrackedSymbols :> {kans, pI, pH, gridData}]]

demo

| improve this answer | |
$\endgroup$
  • $\begingroup$ For some reason with this code the values do not refresh if I move one of the sliders (Mathematica 11.0) $\endgroup$ – GambitSquared Jul 2 '17 at 8:19
  • $\begingroup$ @ImreVégh. There was a comma missing between Initialization :> ... and TrackedSymbols :> ... I have fixed it. Thanks for tell me about the problem. $\endgroup$ – m_goldberg Jul 2 '17 at 13:16
2
$\begingroup$

Here's a simpler example:

data = {1, x};

Manipulate[%, {x, 0, 1}]

My first thought was that this should not work, because I thought Manipulate worked by localizing the literal occurrences of x and maps them to the local DynamicModule variable created for the control {x, 0, 1} when the output is instantiated in the front end. (Most or all of this is explained in the first four tutorials linked in the documentation for Manipulate, which is fairly heavy reading, but essential for understanding tricky things in Manipulate like this issue.) Since there is no x in the body % (which is literally Out[$Line - 1]) of Manipulate[%, {x, 0, 1}], I thought the control's variable x would not be attached to the global symbol x in the value of %.

However, it turns out that Out[] is handled by Manipulate as a special case, and its value is effectively inlined in the body before Manipulate constructs the output. So Manipulate[%, {x, 0, 1}] is effectively equivalent to

Manipulate[{1, x}, {x, 0, 1}]

and the two behave the same.

On the other hand, in

Manipulate[data, {x, 0, 1}]

there is no literal x and the global x in the value of data is not connected to the localized x of the control.

A possible workaround is

Manipulate[data, {x, 0, 1}, LocalizeVariables -> False]

Another:

Manipulate[Evaluate@data, {x, 0, 1}]

But there are better ways. Basically you need to have the body be a function of the control variables.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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