2
$\begingroup$

The following code

bidenNicheBreakdown = {20, 80};
bidenImage = 
  Rasterize[(WebImageSearch["Joe Biden"] // Normal // 
      First )[["Thumbnail"]], ImageSize -> Tiny];
bidenTitle =  
  ToString[bidenImage, StandardForm] <> "\nVoter Breakdown: Joe Biden";
bidenNicheChart = 
 PieChart[bidenNicheBreakdown, 
  ChartLegends -> {"Leftist", "Moderate"}, PlotTheme -> "Web", 
  Frame -> True, FrameTicks -> False, PlotLabel -> bidenTitle, 
  ChartLabels -> bidenNicheBreakdown]

yields

Question 1: Instead of placing the photo of Joe Biden on top of the pie chart, how can I force it to be in the center of the pie chart (and small enough so that it doesn't obstruct the numbers)?

Question 2: If I end up having several of these charts (one for each Democratic primary candidate), is there a command that would allow me to present them in one large image as a grid of images (suitably large enough/rich enough in quality so that someone could see all of their numeric detail when the image is blown up)?

EDIT: I've discovered Grid[]. Is there a way to ensure that each element in the grid is larger?

$\endgroup$
  • 4
    $\begingroup$ Q1: Look up Inset. Starting point: add Epilog -> {Inset[bidenImage]}. Q2: Did you try Grid? $\endgroup$ – Szabolcs Aug 24 at 16:37
5
$\begingroup$

An alternative way to place images in the middle of the chart to avoid occlusion of labels is (1) to prepend the input data with the trivial dataset ({1}) and (2) to use a custom ChartElementFunction to use images as texture for the sector polygons.

To use images as texture for sectors we slightly modify the built-in (but undocumented) chart element function System`BarFunctionDump`TextureRadius:

ClearAll[txtrBar, cEF]
txtrBar[t_] :=  System`BarFunctionDump`TextureRadius[#, #2, "Placement" -> "Fill"] /. 
        Texture[_] :> t &;

cEF[cedf_: ChartElementData["Sector"]] := If[#3 === {}, cedf[##], #3[[1]][##]] &

Examples:

data = {{10, 20}, {40, 60}, {50, 20, 10}};

images = ExampleData[{"TestImage", #}] & /@ {"Lena", "Girl3", "Mandrill"};

dataandimages = MapThread[{{1 -> txtrBar[Texture @ #2]}, 
     Labeled[#, Style[#, 16]] & /@ #} &, {data, images}];

charts = PieChart[#, ChartStyle -> 97, ImageSize -> 300, 
     SectorSpacing -> .25, ChartElementFunction -> cEF[]] & /@ dataandimages;

Legended[Row[charts], 
  Placed[SwatchLegend[97, "legend label" <> ToString[#] & /@ {1, 2, 3}], Right]]

enter image description here

Change cEF[] to cEF[ChartElementData["OscillatingSector", "AngularFrequency" -> 15, "RadialAmplitude" -> 0.1] to get

enter image description here

Replace "OscillatingSector" with "NoiseSector" to get:

enter image description here

fifteencharts = RandomChoice[Show[#, ImageSize -> 150]& /@ charts, 15];
legend = SwatchLegend[97, "legend label" <> ToString[#] & /@ {1, 2, 3}, 
  LegendLayout -> {"Row", 1}];

Legended[Grid[Partition[fifteencharts, 5]], Placed[legend, Top]

enter image description here

Panel[Grid[Partition[fifteencharts, 5]], legend]

enter image description here

$\endgroup$
2
$\begingroup$

You can also

  1. Crop the images circularly using a combination of Texture and CirclePoints,
  2. Make room in the center of the chart using the second element of the option setting SectorOrigin, e.g., SectorOrigin -> {{0, 1}, 1}
  3. Use the resulting images as Epilog in PieChart

data = {{10, 20}, {40, 60}, {50, 20, 10}};

images = ExampleData[{"TestImage", #}] & /@ {"Lena", "Girl3", "Mandrill"};

epilogs = {EdgeForm[{AbsoluteThickness[10], White}], Texture[#], 
  Polygon[CirclePoints[50], VertexTextureCoordinates -> Automatic]} & /@ images;

Graphics /@ epilogs // Row

enter image description here

charts = MapThread[
   PieChart[#, ChartLabels -> #, ChartStyle -> 97, LabelStyle -> 16, 
     ImageSize -> 300, SectorOrigin -> {{0, 1}, 1},
     ChartElementFunction -> "OscillatingSector", 
     Epilog -> #2] &, 
  {data, epilogs}];

legend = SwatchLegend[97, "legend label" <> ToString[#] & /@ {1, 2, 3}, 
     LegendLayout -> {"Row", 1}];

Legended[Row[charts], Placed[legend, Top]]

enter image description here

$\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.