File Exchange Pick of the Week

Our best user submissions

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

|
  • print

Comments

To leave a comment, please click here to sign in to your MathWorks Account or create a new one.