# How do I control the spacing and font size for my plot legend?

I have a Manipulate-based figure in which I'd like to place a compact legend in the upper left corner (within the figure's frame). But by default, the items in the legend are spaced too far apart, and have a font that's too big (and different from the font used for the axes and other labels): How do I control the spacing and font size for my plot legend? I've tried all the answers I've found here that seem relevant, but I fear that even if I hit on the potentially right one, it isn't clear where to apply the solution in the context of my code.

Ideally, I'd like a solution that simplifies the code as a whole, or at least doesn't make it more complex. I've long passed the point I often reach in Mathematica where I think: "I should have just done this in Python!"

sigmoid[z_]:= E^z/(E^z+1)
relu[z_]:=Max[{0, #}]&/@z
softplus[z_]:=Log[1+E^z]

Manipulate[
total=E^rng/saturation;
Show[{
Plot[{E^z/total},  {z, -rng, Log[saturation*total](*==rng*)},  PlotRange->{{-rng, rng},  {0, prng}},
PlotLegends->Placed[{StringForm["Softmax (1%)", NumberForm[saturation*100, {3, 1}]]}, {Left, Top}], PlotStyle->Blue,
Epilog->{Text[Style[N[E^rng/total, 4]], {rng+.3,  E^rng/total}, {-0.5, 0}]}],
Plot[{sigmoid@z},  {z, -rng, rng},  PlotRange->{{-rng, rng},  {0, prng}},
PlotLegends->Placed[{"Sigmoid"}, {Left, Top}],  PlotStyle->Orange],
Plot[{relu@z}, {z, -rng, rng}, PlotRange->{{-rng, rng},  {0, prng}},
PlotLegends->Placed[{"ReLU"}, {Left, Top}], PlotStyle->Purple],
Plot[{softplus@z}, {z, -rng, rng}, PlotRange->{{-rng, rng},  {0, prng}},
PlotLegends->Placed[{"Softplus"}, {Left, Top}], PlotStyle->Green]
}, FrameLabel->{"z", "a(z)"}, AxesOrigin->{-rng, 0}, Frame->True,
Prolog->{GrayLevel[.95], Line[{{0, 0}, {0, prng}}],  Dashed,  Line[{{-rng, 1.0}, {rng, 1.0}}]},
{{rng, 5,  "Logit (z) range"}, 1, 10},
{{saturation,  1, "Logit concentration"}, 1, 1/n, 0.001}, (* Activation,  a(z),  fraction in highest *)
Delimiter,
{{n, 10, "Classes (has no effect)"}, 1, 50, 1,  Visible->False},
{{prng, 1.1, "Activation (a) scale range"}, 1.0, 2*rng}]

• How about replacing your PlotLegends with something like this Placed[LineLegend[{Red}, {Style["Softplus", FontSize -> 10]}, LegendMargins -> 0], {Left, Top}]? – swish Aug 16 '17 at 20:55
• Why do you use Show on 4 separate plots instead of just using one Plot with 4 separate functions? – Carl Woll Aug 16 '17 at 21:01
• @CarlWoll: See my comment to kglr's answer. – orome Aug 16 '17 at 21:56

sigmoid[z_] := E^z/(E^z + 1)
relu[z_] := Max[{0, #}] & /@ z
softplus[z_] := Log[1 + E^z]

Manipulate[total = E^rng/saturation;
Plot[{ConditionalExpression[E^z/total, -rng <= z <= Log[saturation total]],
sigmoid@z, relu@z, softplus@z}, {z, -rng, rng},
PlotRange -> {{-rng, rng}, {0, prng}}, AxesOrigin -> {-rng, 0},
Frame -> True, PlotStyle -> {Blue, Orange, Purple, Green}, ImageSize -> 500,
PlotRangeClipping -> False, PlotRangePadding -> Automatic,
ImagePadding -> {{Automatic, 45}, {Automatic, Automatic}},
Epilog -> {Text[Style[N[E^rng/total, 4]], {rng + .3, E^rng/total}, {-0.5, 0}],
GrayLevel[.9], Line[{{0, 0}, {0, prng}}], Dashed,
Line[{{-rng, 1.0}, {rng, 1.0}}]}, FrameLabel -> {"z", "a(z)"},
PlotLegends -> Placed[LineLegend[Automatic,
{StringForm["Softmax (1%)", NumberForm[saturation*100, {3, 1}]],
"Sigmoid", "ReLU", "Softplus"},
"Spacings" -> {.5, .1}, LabelStyle -> 16], {Left, Top}]],
{{rng, 5, "Logit (z) range"}, 1, 10},
{{saturation, 1, "Logit concentration"}, 1, 1/n, 0.001},
Delimiter,
{{n, 10, "Classes (has no effect)"}, 1, 50, 1, Visible -> False},
{{prng, 1.1, "Activation (a) scale range"}, 1.0, 2*rng}] Note: You can use LegendLayout -> (Grid[##, Spacings -> {.5, .1}, Alignment -> Left] &) instead of "Spacings" -> {.5,.1} on macOS to avoid red syntax highlighting.

• Nice solution. I hadn't thought of that approach to achieving a different domain for the softmax function (actually, it doesn't need to be different, as you'll see if you substitute total and solve, but it's still good to know that trick. I'll need to study how you managed to get the text on the outside of the graph using this method (one Plot): that didn't work for me earlier when I first tried it (many times). – orome Aug 16 '17 at 21:56
• @raxa, I didn't make any changes in your code to get the text outside the graph. Your Epilog and ImagePadding settings places the text in the right place. – kglr Aug 16 '17 at 23:07
• I had to put things into several Plots for it to work before. No idea why! – orome Aug 16 '17 at 23:10
• Confirming that this works. But (FWIW) I just don't understand why I need to create a low level Placed@LineLegend to accomplish what should be a basic part of any legend: spacing and font size. Also that red quoted "Spacings" option worries me. Is there nothing more reliable? – orome Aug 17 '17 at 15:16
• @raxa, you can control the font sizes by wrapping labels with Style[#, 16] without having to use LineLegend[...] (i.e., PlotLegends -> Placed[Style[#, 16] & /@ {StringForm["Softmax (1%)", NumberForm[saturation*100, {3, 1}]], "Sigmoid", "ReLU", "Softplus"}, {Left, Top}] works). However, i don't know a more convenient way to control spacings. Btw, I don't get red highlighting for "Spacings" in version 9 and version 11. – kglr Aug 17 '17 at 21:58

you can specify the position and other options of the elements in PlotLegends. you can read the rules in the legends placement section here http://reference.wolfram.com/language/ref/PlotLegends.html

here is an example of your code with fonts ,color,position and spacing modified. I was not able to avoid the "{ }" around the text though, maybe someone else will tell explain it to us

sigmoid[z_] := E^z/(E^z + 1)
relu[z_] := Max[{0, #}] & /@ z
softplus[z_] := Log[1 + E^z]

Manipulate[total = E^rng/saturation;
Show[{Plot[{E^z/total}, {z, -rng,
Log[saturation*total](*\[Equal]rng*)},
PlotRange -> {{-rng, rng}, {0, prng}},
PlotLegends ->
Placed[{Text[
Style[StringForm["Softmax (1%)",
NumberForm[saturation*100, {3, 1}]], Blue, 7]]}, {{0.11,
0}, {0, -5.6}}], PlotStyle -> Blue,
Epilog -> {Text[
Style[N[E^rng/total, 4]], {rng + .3, E^rng/total}, {-0.5,
0}]}], Plot[{sigmoid@z}, {z, -rng, rng},
PlotRange -> {{-rng, rng}, {0, prng}},
PlotLegends ->
Placed[{Text[Style[{"Sigmoid"}, Italic, Orange, 7]]}, {{0.11,
0}, {0, -5.2}}], PlotStyle -> Orange],
Plot[{relu@z}, {z, -rng, rng},
PlotRange -> {{-rng, rng}, {0, prng}},
PlotLegends ->
Placed[{Text[Style[{"Relu"}, Italic, Purple, 7]]}, {{0.11,
0}, {0, -5}}], PlotStyle -> Purple],
Plot[{softplus@z}, {z, -rng, rng},
PlotRange -> {{-rng, rng}, {0, prng}},
PlotLegends ->
Placed[{Text[Style[{"SoftPlus"}, Italic, Red, 7]]} , {{0.11,
0}, {0, -4.7}}], PlotStyle -> Green]},
FrameLabel -> {"z", "a(z)"}, AxesOrigin -> {-rng, 0}, Frame -> True,
Prolog -> {GrayLevel[.95], Line[{{0, 0}, {0, prng}}], Dashed,
Line[{{-rng, 1.0}, {rng, 1.0}}]}, PlotRangeClipping -> False,
ImagePadding -> {{Automatic, 45}, {Automatic, Automatic}}], {{rng,
5, "Logit (z) range"}, 1,
10}, {{saturation, 1, "Logit concentration"}, 1, 1/n,
0.001},(*Activation,a(z),fraction in highest*)Delimiter, {{n, 10,
"Classes (has no effect)"}, 1, 50, 1,
Visible -> False}, {{prng, 1.1, "Activation (a) scale range"}, 1.0,
2*rng}] • Great job! To reduce the verbosity the Text wrapper around Style in the PlotLegends -> Placed[... expressions is not required. Works fine with only Style. – Jack LaVigne Aug 16 '17 at 22:31