Scatter Bars
Sean's pick this week is scatterbar3 by Manu Raghavan.
Contents
Drawing Bars
If you've ever wanted to draw a bar plot in MATLAB, you've probably come across: bar, barh, bar3, bar3h, and maybe in newer releases histogram or histogram2.
These allow you to do a variety of bar plots with with options for stacking and alignment. For example,
y = rand(5,1); y = [y 1-y]; bars = bar3h(1:5,y,'stacked'); legend(bars,{'Type A','Type B'})
Or:
bars = bar(1:7,abs([0.7 0.5 0; 0.6 0.5 0; 0.55 0.5 0.1; 0.52 0.5 0.2; 0.4 0.5 0.4; 0.9 0 0.5; 0.9 0 0.4])); ax = gca; ax.YLim = [0 1]; ax.XTickLabel = day(datetime(1,1,1:7),'shortname'); legend(bars,{'Sleep','Coffee','Beer'},'location','northwest')
However these require a grid. The grid does not have to be uniform but does have to be monotically increasing.
histogram2(randn(100,1),randn(100,1))
Drawing The Boston Skyline
So what if I wanted to draw the Boston skyline? Now I'll need a non-uniform grid. To get the data into MATLAB, I copied
the table from Wikipedia into Excel and then imported it into MATLAB as a table.
load BostonBuildings
disp(BostonBuildings)
BuildingName BuildingHeight LatLonDMS _______________________________ ______________ _____________________________ '200 Clarendon' '790 (241)' '42°20′57.4″N 71°04′29.2″W' 'Prudential Tower' '749 (228)' '42°20′49.78″N 71°04′57.08″W' 'Millennium Tower' '685 (209)' '42°21′21.01″N 71°3′33.91″W' 'Federal Reserve Bank Building' '614 (187)' '42°21′08.55″N 71°03′14.82″W' 'One Boston Place' '601 (183)' '42°21′31″N 71°03′30″W' 'One International Place' '600 (183)' '42°21′20.8″N 71°03′07.5″W' '100 Federal Street' '591 (180)' '42°21′18″N 71°03′22″W' 'One Financial Center' '590 (180)' '42°21′08.6″N 71°03′23.0″W' '111 Huntington Avenue' '554 (169)' '42°20′48.38″N 71°04′52.86″W' 'Two International Place' '538 (164)' '42°21′23″N 71°03′06″W' 'One Post Office Square' '525 (160)' '42°21′25″N 71°03′19″W' 'One Federal Street' '520 (159)' '42°21′24″N 71°03′25″W' 'Exchange Place' '510 (156)' '42°21′30″N 71°03′23″W' '60 State Street' '509 (155)' '42°21′33″N 71°03′23″W' 'One Beacon Street' '505 (154)' '42°21′30″N 71°03′39″W' 'One Lincoln Street' '503 (153)' '42°21′09″N 71°03′29″W' '28 State Street' '500 (152)' '42°21′34″N 71°03′27″W' 'Custom House Tower' '496 (151)' '42°21′32.65″N 71°03′12.13″W' 'Berkeley Building' '495 (151)' '42°20′59.78″N 71°04′21.55″W' '33 Arch Street' '477 (145)' '42°21′21″N 71°03′28″W' 'State Street Bank Building' '477 (145)' '42°21′22″N 71°03′15″W' 'Millennium Place Tower I' '475 (145)' '42°21′11″N 71°03′47″W' '125 High Street' '452 (138)' '42°21′19″N 71°03′12″W' '100 Summer Street' '450 (137)' '42°21′14″N 71°03′27″W' 'Millennium Place Tower II' '446 (136)' '42°21′11″N 71°03′47″W' 'McCormack Building' '401 (122)' '42°21′34″N 71°03′44″W' 'Keystone Building' '400 (122)' '42°21′15″N 71°03′16″W' 'Harbor Towers I' '400 (122)' '42°21′28.64″N 71°02′59.89″W'
I need to remove meters from height and convert latitude in Degrees-Minutes-Seconds (DMS) to latitude and longitude in degrees.
First the height, all buildings have three digits so I'll turn the first three digits into a number.
BostonBuildings.BuildingHeight = cellfun(@(x)str2double(x(1:3)),BostonBuildings.BuildingHeight);
Next DMS to lat/lon. There's a nice function in the Mapping Toolbox, dms2degrees, to do exactly this. First, I need to split the strings into pieces. So far, I've taken the easy way to get the data in and manipulate it. Now I'll make things harder on myself and wake my brain up for the day with some regular expressions. Here's the expression:
expression = '([\d.]{1,5})';
Let me explain that in English:
- () around whole expression this captures the token, the string I'm matching so that I can use it later. Use () and the 'tokens' flag to extract the contents of the string.
- [] Allows anything inside of the brackets to count as a match.
- \d. Says I can match digits, \d, or periods.
- {1,5} This means I can match digits and periods 1 to 5 times to capture a single digit or 28.64, five digits long.
t = regexp(BostonBuildings.LatLonDMS,expression,'tokens');
The result is a cell because regexp doesn't know how many tokens it will match, if any. Unpack the cell by vertically concatenating
and then turning the first element of each resulting cell into a number (they're still strings):
dmsdms = vertcat(t{:}); dmsdms = cellfun(@(x)str2double(x{1}),dmsdms);
Now we use the Mapping Toolbox function give us latitude and longitude in degrees and stick that back into the table.
BostonBuildings.LatDeg = dms2degrees(dmsdms(:,1:3)); % First three lat BostonBuildings.LonDeg = dms2degrees(dmsdms(:,4:6)); % Second three lon disp(BostonBuildings(1:5,{'BuildingName','BuildingHeight','LatDeg','LonDeg'}))
BuildingName BuildingHeight LatDeg LonDeg _______________________________ ______________ ______ ______ '200 Clarendon' 790 42.349 71.075 'Prudential Tower' 749 42.347 71.083 'Millennium Tower' 685 42.356 71.059 'Federal Reserve Bank Building' 614 42.352 71.054 'One Boston Place' 601 42.359 71.058
The locations are in latitude and longitude, I'll project them into x/y for plotting using projfwd.
[x, y] = projfwd(defaultm('mercator'),BostonBuildings.LatDeg,BostonBuildings.LonDeg);
Finally, we can call scatterbar3 rescaling.
scatterbar3(x*10,y*10,BostonBuildings.BuildingHeight,0.00025) ax = gca; ax.XTick = []; ax.YTick = []; view(16,8) % Approximate view from Mass Pike Eastbound zlabel('Height (ft)')
For those of you who live in or near Boston and have no clue what that third tallest building is, it's the Millenium
Tower under construction right now.
Comments
Would having scatterbar3 be helpful to you? What types of data would you want to visualize with it?
Let us know by leaving a here comment here> or leave a comment for Manu here.
Published with MATLAB® R2016a
- Category:
- Picks
Comments
To leave a comment, please click here to sign in to your MathWorks Account or create a new one.