Group Abstract Group Abstract

Message Boards Message Boards

Can this geo-3D histogram of USA population be improved?

Posted 12 years ago

I am looking for an optimal code to build a 3D histogram of USA population with bars bounded by state borders. Here is my initial version. Can anyone suggest improvements?

(* get the states *)
divisions = 
  EntityValue[Entity["AdministrativeDivision", {_, "UnitedStates"}], 
   "Entities"];

(* get polygons of borders *)
dat = EntityValue[
    divisions, {"Population", "Polygon"}] /. {GeoPosition -> Identity,
     Quantity[x_, _] -> x};

(* some arbitrary rescaling to improve relative height perception *)
pop = Rescale[(# - Min[#]) &@Log[dat[[All, 1]]] // N];

(* plot constants of population of regions of polygons *)
polygs = Plot3D[#1, {x, y} \[Element] #2, Mesh -> None, Filling -> 0, 
     ColorFunction -> "Rainbow", ColorFunctionScaling -> False] & @@@ 
   Transpose[{pop, dat[[All, 2]]}];

(* combine all *)
Show[polygs, PlotRange -> {{23, 50}, {-60, -130}, All}, 
 BoxRatios -> {27, 70, 50}, ImageSize -> 800, Boxed -> False, 
 Axes -> False]

enter image description here

enter image description here

POSTED BY: Vitaliy Kaurov
11 Replies

Yes. But, my goal here is different.

I am looking for something that is more intuitive for students and beginners. Yours are good examples for just-beyond-beginners who are learning about pattern restrictions. For beginners, wouldn't DeleteEntities[entityList, {entityPattern, entityPattern}] be more initially more useful than writing it oneself?

POSTED BY: W. Craig Carter
Posted 12 years ago

DeleteCases do almost same thing you described:

DeleteCases[divisions, Entity[_, {"Alaska" | "Hawaii", _}]]

or

DeleteCases[el, Entity[_,"Venus"]]
POSTED BY: Jaebum Jung
POSTED BY: W. Craig Carter
Posted 12 years ago

you could do :

el = EntityList["Planet"];
DeleteCases[el, a_ /; MemberQ[a, "Venus", Infinity]]

divisions = 
 EntityValue[Entity["AdministrativeDivision", {_, "UnitedStates"}],   "Entities"];
DeleteCases[divisions,   a_ /; MemberQ[a, "Alaska" | "Hawaii", Infinity]]

for states you can also do:

divisions = 
 EntityValue[Entity["AdministrativeDivision", {Except["Alaska" | "Hawaii"],   "UnitedStates"}], "Entities"]
POSTED BY: Jaebum Jung
Posted 12 years ago

Here's another approach (it's bit complicated but faster..) :

(* divide polygon pts to clean up artificials when polygon has holes *)
FindContourBreaks[pts_List] := 
  Module[{i, lines, breaks = {}}, 
   lines = {pts[[#[[1]]]], pts[[#[[2]]]]} & /@ 
     Partition[RotateLeft[Flatten[{#, #} & /@ Range[Length[pts]], 1]],
       2];
   Position[lines, 
     Alternatives @@ 
      Intersection[{lines[[All, 2]], lines[[All, 1]]} // Transpose, 
       lines]] // Flatten
   ];

FindContourBreak[pts_List] := 
  Module[{breaks, ranges}, breaks = FindContourBreaks[pts];
   ranges = 
    Partition[
     RotateLeft[Join[{1, 1}, Flatten[{#, # + 1} & /@ breaks]]], 2];
   ranges = Drop[ranges, -1];
   DeleteCases[Range @@@ ranges, x_ /; Length[x] < 3]];

(*generate side polygons - heights *)
SideComplex[pts_List, length_] := 
  Module[{topPts, botPts, sideRects, sidePts, sideNormals},
   topPts = pts;
   botPts = (2 length + 1 - #) & /@ topPts;
   sideRects = 
    Partition[
     RotateLeft[Flatten[{#, #} & /@ Range[Length[topPts]], 1]], 2];
   sidePts = {topPts[[#[[1]]]], botPts[[#[[1]]]], botPts[[#[[2]]]], 
       topPts[[#[[2]]]]} & /@ sideRects;
   Polygon@sidePts];

(* main code - it create top, bottom, and side polygons *)
To3DComplex[Polygon[list_], depth_: 10] := To3DComplex[list, depth]

To3DComplex[list_List, depth_: 10] /; (Depth[list] == 3) := 
 Module[{topPts, botPts, length, contours, sidePolys},
  topPts = {#[[1]], #[[2]], depth} & /@ list;
  botPts = Reverse[{#[[1]], #[[2]], 0} & /@ topPts];
  length = Length[list];
  contours = FindContourBreak[list];
  sidePolys = SideComplex[#, length] & /@ contours;
  GraphicsComplex[
   Join[topPts, botPts], {Polygon[Range[length]], 
    Polygon[Range[length + 1, 2 length] // Reverse], EdgeForm[], 
    sidePolys}]
  ]

To3DComplex[list_List, depth_: 10] := To3DComplex[#, depth] & /@ list

Here's example:

divisions = 
  EntityValue[Entity["AdministrativeDivision", {_, "UnitedStates"}], 
   "Entities"];

project geoposition to mercator :

dat = (EntityValue[divisions, {"Population", "Polygon"}] /. 
      GeoPosition[x_] :> 
       GeoGridPosition[GeoPosition[x], "Mercator"]) /. 
    GeoGridPosition[x_, "Mercator"] :> x /. Quantity[x_, _] :> x;

rescale population for color function and depth:

pop = Rescale[(# - Min[#]) &@Log[dat[[All, 1]]] // N];

final result (I multiply 20 for depth):

poly = {ColorData["Rainbow"][#1], To3DComplex[#2, 20 #1]} & @@@ 
   Transpose[{pop, dat[[All, 2]]}];

Graphics3D[poly, PlotRange -> {{-60, -130}, {23, 60}, All}, 
 ImageSize -> 800, Boxed -> False]

enter image description here

POSTED BY: Jaebum Jung
POSTED BY: W. Craig Carter

I like Craigs idea of visualization very much. A lot of white space is generated by presence of islands. Here is the central pieces to enjoy the approach fully:

enter image description here

POSTED BY: Vitaliy Kaurov

Dear Vitaliy,

very nice indeed! I wanted to have a look at that but interestingly my system:

"10.0 for Mac OS X x86 (64-bit) (June 29, 2014)"

reproducibly crashes during the execution of the last command. I can send you the crash report.

Best wishes, Marco

POSTED BY: Marco Thiel

Thanks for the kind words and sorry for the crash. Please do send the report. I wonder if anyone else experience this.

POSTED BY: Vitaliy Kaurov

Dear Vitaliy,

I have submitted the report. Also I tried four Macs with slightly different specifications, all on Mavericks, and they all crash at the same command.

Cheers, Marco

POSTED BY: Marco Thiel

Duplicated the crash on a MacOS 10.9.4 machine. Ran fine on MacOS 10.8.5 and Windows 7.
Mixed results on Linux.

Problem report filed.

POSTED BY: Bruce Miller
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard