function ValueAdjForYear2=adjustpc(ValueForYear1,Year1,Year2)
%ADJUSTPC Adjust per capita using historical U.S. population data.
%
% ADJUSTPC(VALUEFORYEAR1,YEAR1,YEAR2) adjusts the number VALUEFORYEAR1 from
% what it was in YEAR1 to what it was in YEAR2. The adjustment is per
% capita, based on historical population data previously obtained from the
% U.S. Census Bureau.
%
% VALUEFORYEAR1 can be any number. YEAR1 and YEAR2 each can both be any
% year from 1900 to the current year. YEAR2 is optional, with its default
% value being the current year.
%
% The input arguments can either be single numbers, or row or column
% vectors of the same size.
%
% Population data is read from the the data file. It is assumed that the
% file contains data for both YEAR1 and YEAR2. This file can be updated
% using a text editor - if and when this needs to be done. Microsoft Excel
% should not be used to do this, as it can alter the date format. The
% updated file must contain data for all years up to the current year.
%
% EXAMPLES:
%
% adjustpc(1,1900,2007) returns 3.9542
% Because in this case ValueForYear1 equals 1, this indicates that the
% population in 2007 was 3.9542 times that in 1900.
%
% adjustpc(1,1900) also returns 3.9542
% adjustpc(1,2007,1900) returns 0.2529
%
% adjustpc(10,1945,1960) returns 12.9117
% This indicates that 10 units of something (e.g. dollars) for the entire
% population in 1945 would correspond to having 12.9117 units of that
% thing for the entire population in 1960.
%
% ValueForYear1=[4 1 15];
% Year1=[1920 1973 2002];
% Year2=repmat(2005,size(Year1));
% adjustpc(ValueForYear1,Year1,Year2) returns [11.1405 1.3992 15.4363]
%
% REMARKS:
%
% - For efficiency, population data is read from the data file into RAM
% only once per session, after which it stays in RAM for the remainder of
% the session. For more implementation details, see the relevant
% PopForYear subfunction section of the code.
%
% VERSION: 20070720
% MATLAB VERSION: 7.4.0.287 (R2007a)
% LICENSE: As-is; public domain
%
% See also CSVREAD, PERSISTENT.
%{
VERSION HISTORY:
20070720: - Compacted some code.
20070703: - Added MATLAB version check.
20070409: - Original version.
KEYWORDS:
adjust, adjustment, per capita, population, census, historical
%}
%% Check MATLAB version
if datenum(version('-date'))<datenum('29-Jan-2007')
error(['The MATLAB version in use is ',version('-release'),'. ',...
'This function requires at least version 2007a.'])
end
%% Declare any needed input arguments (vectorized)
if nargin<2
help adjustpc
return
elseif nargin<3
Year2=str2double(datestr(date,10));
Year2=repmat(Year2,size(Year1));
end
%% Do some input validation
assert(all([isnumeric(ValueForYear1) ...
isnumeric(Year1) isnumeric(Year2)]),...
'All input arguments must be numeric.')
assert(isequal(size(ValueForYear1),size(Year1)) && ...
isequal(size(ValueForYear1),size(Year2)),...
'All input argments must have the same size.')
assert(all(all([Year1 Year2]>=1900)),...
'Both years must be at least 1900.')
assert(all(all([Year1 Year2]<=str2double(datestr(date,10)))),...
'Neither year can be greater than the current year.')
%% Handle trivial cases efficiently
if isequal(Year1,Year2) || ~any(ValueForYear1)
ValueAdjForYear2=ValueForYear1;
return
end
%% Calculate adjusted value
if size(ValueForYear1,1)>size(ValueForYear1,2)
ValueAdjForYear2=ValueForYear1.*(PopForYear(Year2)./PopForYear(Year1));
else
ValueAdjForYear2=ValueForYear1.*(PopForYear(Year2)./PopForYear(Year1))';
end
%% Subfunction: get population for a particular year
function[Pop]=PopForYear(Year)
%Declare persistent variable for population data
persistent PopsByYear
%Conditionally read population data
if isempty(PopsByYear) || any((Year-1900+1)>numel(PopsByYear))
PopsByYear=csvread('adjustpc.population_estimates.csv',1,2);
end
%Verify that the data file contains data for the relevant years
assert(all((Year-1900+1)<=numel(PopsByYear)),...
['Ensure that the data file contains data ',...
'for all years up to the last relevant year.'])
%Determine population for relevant years
Pop=PopsByYear(Year-1900+1);