Question
AddressToLatLon.m %% %% AddressToLatLon %% %% Given a street address, returns (latitude, longitude). %% %% Example: %% [lat, lon] = AddressToLatLon('851 S. Morgan St, Chicago
AddressToLatLon.m
%%
%% AddressToLatLon
%%
%% Given a street address, returns (latitude, longitude).
%%
%% Example:
%% [lat, lon] = AddressToLatLon('851 S. Morgan St, Chicago IL');
%%
%%
%% References:
%% https://www.mathworks.com/matlabcentral/fileexchange/24126-google-geocode-api
%% https://www.mathworks.com/matlabcentral/fileexchange/20565-json-parser
%%
%%
function [lat,lon] = AddressToLatLon(address)
retries = 3;
while retries > 0
try
%% try to get (latitude, longitude) from google:
address = strrep(address, ' ', '%20');
google = ['https://maps.googleapis.com/maps/api/geocode/json?address=',address];
result = parse_json(urlread(google));
lat = result{1}.results{1}.geometry.location.lat;
lon = result{1}.results{1}.geometry.location.lng;
break; %% success, break out of the loop
catch ME
%% it failed, let's try again (at most 3 times):
retries = retries - 1;
lat = 0;
lon = 0;
pause(1.0); %% wait 1 second before trying again:
end
end
end
function [data json] = parse_json(json)
% [DATA JSON] = PARSE_JSON(json)
% This function parses a JSON string and returns a cell array with the
% parsed data. JSON objects are converted to structures and JSON arrays are
% converted to cell arrays.
%
% Example:
% google_search = 'http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=matlab';
% matlab_results = parse_json(urlread(google_search));
% disp(matlab_results{1}.responseData.results{1}.titleNoFormatting)
% disp(matlab_results{1}.responseData.results{1}.visibleUrl)
data = cell(0,1);
while ~isempty(json)
[value json] = parse_value(json);
data{end+1} = value; %#ok
end
end
function [value json] = parse_value(json)
value = [];
if ~isempty(json)
id = json(1);
json(1) = [];
json = strtrim(json);
switch lower(id)
case '"'
[value json] = parse_string(json);
case '{'
[value json] = parse_object(json);
case '['
[value json] = parse_array(json);
case 't'
value = true;
if (length(json) >= 3)
json(1:3) = [];
else
ME = MException('json:parse_value',['Invalid TRUE identifier: ' id json]);
ME.throw;
end
case 'f'
value = false;
if (length(json) >= 4)
json(1:4) = [];
else
ME = MException('json:parse_value',['Invalid FALSE identifier: ' id json]);
ME.throw;
end
case 'n'
value = [];
if (length(json) >= 3)
json(1:3) = [];
else
ME = MException('json:parse_value',['Invalid NULL identifier: ' id json]);
ME.throw;
end
otherwise
[value json] = parse_number([id json]); % Need to put the id back on the string
end
end
end
function [data json] = parse_array(json)
data = cell(0,1);
while ~isempty(json)
if strcmp(json(1),']') % Check if the array is closed
json(1) = [];
return
end
[value json] = parse_value(json);
if isempty(value)
ME = MException('json:parse_array',['Parsed an empty value: ' json]);
ME.throw;
end
data{end+1} = value; %#ok
while ~isempty(json) && ~isempty(regexp(json(1),'[\s,]','once'))
json(1) = [];
end
end
end
function [data json] = parse_object(json)
data = [];
while ~isempty(json)
id = json(1);
json(1) = [];
switch id
case '"' % Start a name/value pair
[name value remaining_json] = parse_name_value(json);
if isempty(name)
ME = MException('json:parse_object',['Can not have an empty name: ' json]);
ME.throw;
end
data.(name) = value;
json = remaining_json;
case '}' % End of object, so exit the function
return
otherwise % Ignore other characters
end
end
end
function [name value json] = parse_name_value(json)
name = [];
value = [];
if ~isempty(json)
[name json] = parse_string(json);
% Skip spaces and the : separator
while ~isempty(json) && ~isempty(regexp(json(1),'[\s:]','once'))
json(1) = [];
end
[value json] = parse_value(json);
end
end
function [string json] = parse_string(json)
string = [];
while ~isempty(json)
letter = json(1);
json(1) = [];
switch lower(letter)
case '\' % Deal with escaped characters
if ~isempty(json)
code = json(1);
json(1) = [];
switch lower(code)
case '"'
new_char = '"';
case '\'
new_char = '\';
case '/'
new_char = '/';
case {'b' 'f' 'n' 'r' 't'}
new_char = sprintf('\%c',code);
case 'u'
if length(json) >= 4
new_char = sprintf('\\u%s',json(1:4));
json(1:4) = [];
end
otherwise
new_char = [];
end
end
case '"' % Done with the string
return
otherwise
new_char = letter;
end
% Append the new character
%%string = [string char(new_char)]; %#ok
string = strcat(string, char(new_char));
end
end
function [num json] = parse_number(json)
num = [];
if ~isempty(json)
% Validate the floating point number using a regular expression
[s e] = regexp(json,'^[\w]?[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?[\w]?','once');
if ~isempty(s)
num_str = json(s:e);
json(s:e) = [];
num = str2double(strtrim(num_str));
end
end
end
DistBetween2Points.m
%%
%% Returns the distance in miles between 2 points
%% (lat1, lon1) and (lat2, lon2). One set must
%% be a point, however the other can be a single
%% point OR a vector --- in which case a vector
%% of distances is returned.
%%
%%
function Distance = DistBetween2Points(lat1, lon1, lat2, lon2)
%%
%% Reference: http://www8.nau.edu/cvm/latlon_formula.html
%%
earth_rad = 3963.1; %% statue miles:
lat1_rad = lat1 .* pi ./ 180.0;
lon1_rad = lon1 .* pi ./ 180.0;
lat2_rad = lat2 .* pi ./ 180.0;
lon2_rad = lon2 .* pi ./ 180.0;
%% distance between points in statue miles:
Distance = earth_rad .* acos(...
(cos(lat1_rad).*cos(lon1_rad).*cos(lat2_rad).*cos(lon2_rad)) ...
+ ...
(cos(lat1_rad).*sin(lon1_rad).*cos(lat2_rad).*sin(lon2_rad)) ...
+ ...
(sin(lat1_rad).*sin(lat2_rad)) ...
);
end
DivvyAnalysis.m
function Result = DivvyAnalysis(filename, analysis, optional)
%%
%% let's make sure the file exists:
%%
if exist(filename, 'file') ~= 2
fprintf('**Error: file "%s" cannot be found ', filename);
Result = '**Error: file not found';
return;
end
%%
%% Load the data:
%%
data = load(filename);
%%
%% Perform requested analysis:
%%
if analysis == 1
Result = NumRides(data);
elseif analysis == 2
Result = AverageRide(data);
elseif analysis == 3
Result = RiderPercentage(data, optional);
elseif analysis == 4
Result = AverageAge(data, optional);
elseif analysis == 5
Result = RideHistogram(data, optional);
elseif analysis == 6
Result = StationCheckouts(data, optional);
elseif analysis == 7
Result = StationCheckins(data, optional);
elseif analysis == 8
Result = Top10Checkouts(data);
elseif analysis == 9
Result = Top10Checkins(data);
else
Result = '**Error: invalid analysis parameter';
end
end
%% total # of rides in this dataset:
function Rides = NumRides(data)
[Rides, ~] = size(data);
end
%% average ride duration, in seconds:
function AvgRide = AverageRide(data)
AvgRide = mean(data(:, 5)); %% trip duration in column 5:
AvgRide = AvgRide / 60.0; %% convert to mins:
end
%% percentage of male (1) or female (2) riders:
function Percentage = RiderPercentage(data, gender)
LI = (data(:, 7) == gender);
Riders = NumRides(data);
Percentage = (sum(LI) / Riders) * 100.0;
end
%% average age of male (1) or female (2) riders:
function AvgAge = AverageAge(data, gender)
LI = ((data(:, 6) > 0) & (data(:, 7) == gender));
birthyears = data(LI, 6); %% extract matching gender with birthyears > 0
%% compute age of rider:
c = clock();
currentyear = c(1); %% year is first entry:
Ages = currentyear - birthyears;
AvgAge = mean(Ages);
end
%% # of rides each hour from midnight to 11pm; pass 0 as "gender" to
%% count all rides, otherwise 1 => male and 2 => female:
function Result = RideHistogram(data, gender)
startingHours = data(:, 4); %% column 4 contains starting hour:
if gender == 0 %% count ALL rides:
Result = histc(startingHours, 0:23); %% 24 bins, 0:23
else
LI = (data(:, 7) == gender); %% search for matching gender:
startingHours = startingHours(LI); %% extract matching rows:
Result = histc(startingHours, 0:23); %% 24 bins, 0:23
end
Result = Result'; %% we want a row vector:
end
%% total # of rides where the ride started at this station:
function Checkouts = StationCheckouts(data, stationID)
LI = (data(:, 1) == stationID); %% column 1 contains starting station:
Checkouts = sum(LI);
end
%% total # of rides where the ride ended at this station:
function Checkins = StationCheckins(data, stationID)
LI = (data(:, 2) == stationID); %% column 2 contains ending station:
Checkins = sum(LI);
end
%% which stations have the largest # of rides that originated here? Return
%% a 10x2 matrix where column 1 are the top-10 station ids and column 2 are
%% the corresponding # of rides starting from these stations:
function Result = Top10Checkouts(data)
ids = data(:, 1); %% column 1 contains starting station IDs:
ids = unique(ids); %% eliminate duplicates:
%%
%% loop can be replaced with histc(data(:, 1), ids);
%%
counts = zeros(length(ids), 1); %% column of 0's
for i = 1:length(ids)
LI = (data(:, 1) == ids(i));
counts(i) = sum(LI);
end
[counts, newOrdr] = sort(counts, 'descend');
ids = ids(newOrdr); %% reorder ids to match:
Result = [ids(1:10), counts(1:10)]; %% top-10 of each:
end
%% which stations have the largest # of rides that ended here? Return
%% a 10x2 matrix where column 1 are the top-10 station ids and column 2 are
%% the corresponding # of rides ending at these stations:
function Result = Top10Checkins(data)
ids = data(:, 2); %% column 2 contains ending station IDs:
ids = unique(ids); %% eliminate duplicates:
%%
%% loop can be replaced with histc(data(:, 1), ids);
%%
counts = zeros(length(ids), 1); %% column of 0's
for i = 1:length(ids)
LI = (data(:, 2) == ids(i));
counts(i) = sum(LI);
end
[counts, newOrdr] = sort(counts, 'descend');
ids = ids(newOrdr); %% reorder ids to match:
Result = [ids(1:10), counts(1:10)]; %% top-10 of each:
end
%%
%% GetStationName
%%
%% Given a Divvy station id, loads the Divvy file 'divvy-stations.csv'
%% and returns the station name associated with this id. Returns
%% the string 'Station not found...' if the given station id is not
%% found.
%%
%% NOTE: you must pass a single id, you cannot pass a vector of ids.
%%
%%
%% Prof. Joe Hummel
%% U. of Illinois, Chicago
%% CS109, Spring 2018
%% Project #13
%%
%%
function Name = GetStationName(id)
filename = 'divvy-stations.csv';
if exist(filename, 'file') ~= 2 %% doesn't exist:
fprintf('**Error in GetStationName: cannot find "divvy-names.csv" file ');
Name = '?';
return;
end
%% load file of station names, and search for matching id:
%% this works in MATLAB or Octave
[IDs, Names] = textread(filename, '%d %s', 'delimiter', ',');
LI = (IDs == id);
if sum(LI) == 1 %% found it!
I = find(IDs == id); %% find index of station id
Name = Names{I}; %% use { } to extract from CELL ARRAY
else
Name = 'Station not found...';
end
end
Assignment In the previous project #12 you wrote functions to analyze a file of Divvy data. This assignment is going to build on those functions to (a) visualize the data, and (b) find stations nearby. Submissions will be collected via Blackboard. Before you start, decide if you are going to use your solution to Project #12, or our provided solution. Either way, make a copy of your DivvyAnalysis.m file and rename it so your solution is not lost if/ when you copy our provided solution. Provided files: .m and.csv files A number of files are being provided to aid in the completion of this assignment; both.m and.csv files. These can be found in the on the course web page: open "Projects", then "project-13". Here are the files: AddressToLatLon.m: function to convert street address to (latitude, longitude) using Google API DistBetween2Points.m: function to compute miles between (lat1, long1) and (lat2, long2) divvvi csv. same input file as proiect #12 Assignment In the previous project #12 you wrote functions to analyze a file of Divvy data. This assignment is going to build on those functions to (a) visualize the data, and (b) find stations nearby. Submissions will be collected via Blackboard. Before you start, decide if you are going to use your solution to Project #12, or our provided solution. Either way, make a copy of your DivvyAnalysis.m file and rename it so your solution is not lost if/ when you copy our provided solution. Provided files: .m and.csv files A number of files are being provided to aid in the completion of this assignment; both.m and.csv files. These can be found in the on the course web page: open "Projects", then "project-13". Here are the files: AddressToLatLon.m: function to convert street address to (latitude, longitude) using Google API DistBetween2Points.m: function to compute miles between (lat1, long1) and (lat2, long2) divvvi csv. same input file as proiect #12
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started