Skip to main content

plotting - Isolating legend from Show combination of plots


Best explained by example. The code,


p1 = Plot[Sin[x], {x, 0, 10}, PlotLegends -> {"sin(x)"}];
p2 = Plot[Cos[x], {x, 0, 10}, PlotLegends -> {"cos(x)"}, PlotStyle -> Red];
p3 = Show[p1, p2]

Gives me this nice picture:


both



Now I want to isolate the plots and legends for export, so I can do,


p1[[1]]
p1[[2, 1]]

Which gives me:


plot


legend


But doing this on the combination p3,


p3[[1]]
p3[[2, 1]]


produces:


plot and one legend


only one legend


where only the legend from the first plot was extracted. Given two plots created separately with individual legends, is there a way to isolate the plot and legends? It seems like I can isolate the plots with p3[[1]][[1]], but haven't managed to combine the legends. I know I can create the legend manually separately, but I'm less keen on doing that.


Is there a way I can inspect the object p3 more closely to answer this question for myself? Currently it seems like trial and error by adding [[1]] indexing everywhere.



Answer




Is there a way I can inspect the object p3 more closely to answer this question for myself?




This is indeed the right question to ask. You can look at the expression structure using InputForm. This is often overwhelming, so we may need to do something to reduce the amount of information that is shown. One way is Short or Shallow.


Shallow[InputForm[p3]]

enter image description here


Shallow[InputForm[p3], 5]

enter image description here


Originally, all graphics were represented with Graphics expression. Show could combine only Graphics expressions. Anything else it could handle it converted to Graphics first.


Legending works by wrapping with Legended.


This is how you construct a legended plot manually:



Legended[
Plot[Sin[x], {x, 0, 10}, PlotStyle -> Blue],
LineLegend[{Blue}, {"sin x"}]
]

This is what is Plot produces automatically as well.


The first element in Legended will be the return value of Plot, a Graphics expression. The second element stays unevaluated as LineLegend[{Blue}, {"sin x"}], however, it displays as a legend. Just like Graphics[...], it does not evaluate to something, it simply displays in a certain way. The expression structure is not modified.


This is the first bit necessary to understand what is happening.


The second bit is that Show is now extended to handle Legended expressions. It does so by combining all the contained Graphics normally and placing them into an innermost Legended. However, the legend expressions (such as LineLegend) are not combined. Instead they are placed in a nested Legended structure which looks like


Legended[

Legended[
combinedGraphics,
legend1
],
legend2
]

Then it is the formatting of Legended that handles displaying this in a proper way.


Comments

Popular posts from this blog

functions - Get leading series expansion term?

Given a function f[x] , I would like to have a function leadingSeries that returns just the leading term in the series around x=0 . For example: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x)] x and leadingSeries[(1/x + 2 + (1 - 1/x^3)/4)/(4 + x)] -(1/(16 x^3)) Is there such a function in Mathematica? Or maybe one can implement it efficiently? EDIT I finally went with the following implementation, based on Carl Woll 's answer: lds[ex_,x_]:=( (ex/.x->(x+O[x]^2))/.SeriesData[U_,Z_,L_List,Mi_,Ma_,De_]:>SeriesData[U,Z,{L[[1]]},Mi,Mi+1,De]//Quiet//Normal) The advantage is, that this one also properly works with functions whose leading term is a constant: lds[Exp[x],x] 1 Answer Update 1 Updated to eliminate SeriesData and to not return additional terms Perhaps you could use: leadingSeries[expr_, x_] := Normal[expr /. x->(x+O[x]^2) /. a_List :> Take[a, 1]] Then for your examples: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x), x] leadingSeries[Exp[x], x] leadingSeries[(1/x + 2 + (1 - 1/x...

How to thread a list

I have data in format data = {{a1, a2}, {b1, b2}, {c1, c2}, {d1, d2}} Tableform: I want to thread it to : tdata = {{{a1, b1}, {a2, b2}}, {{a1, c1}, {a2, c2}}, {{a1, d1}, {a2, d2}}} Tableform: And I would like to do better then pseudofunction[n_] := Transpose[{data2[[1]], data2[[n]]}]; SetAttributes[pseudofunction, Listable]; Range[2, 4] // pseudofunction Here is my benchmark data, where data3 is normal sample of real data. data3 = Drop[ExcelWorkBook[[Column1 ;; Column4]], None, 1]; data2 = {a #, b #, c #, d #} & /@ Range[1, 10^5]; data = RandomReal[{0, 1}, {10^6, 4}]; Here is my benchmark code kptnw[list_] := Transpose[{Table[First@#, {Length@# - 1}], Rest@#}, {3, 1, 2}] &@list kptnw2[list_] := Transpose[{ConstantArray[First@#, Length@# - 1], Rest@#}, {3, 1, 2}] &@list OleksandrR[list_] := Flatten[Outer[List, List@First[list], Rest[list], 1], {{2}, {1, 4}}] paradox2[list_] := Partition[Riffle[list[[1]], #], 2] & /@ Drop[list, 1] RM[list_] := FoldList[Transpose[{First@li...

front end - keyboard shortcut to invoke Insert new matrix

I frequently need to type in some matrices, and the menu command Insert > Table/Matrix > New... allows matrices with lines drawn between columns and rows, which is very helpful. I would like to make a keyboard shortcut for it, but cannot find the relevant frontend token command (4209405) for it. Since the FullForm[] and InputForm[] of matrices with lines drawn between rows and columns is the same as those without lines, it's hard to do this via 3rd party system-wide text expanders (e.g. autohotkey or atext on mac). How does one assign a keyboard shortcut for the menu item Insert > Table/Matrix > New... , preferably using only mathematica? Thanks! Answer In the MenuSetup.tr (for linux located in the $InstallationDirectory/SystemFiles/FrontEnd/TextResources/X/ directory), I changed the line MenuItem["&New...", "CreateGridBoxDialog"] to read MenuItem["&New...", "CreateGridBoxDialog", MenuKey["m", Modifiers-...