5  基礎編

using CSV
using DataFrames
using StringEncodings
using LinearAlgebra
using Optim
using ForwardDiff
using Distributions
for file in ["calculateBRObjective.jl"]
    include("functions/entry_exit/" * file)
end

5.1 データの読み込み

data = CSV.File(
    open(read, "data/entry_exit_basic/MRIData.csv", enc"UTF-8"),
    missingstring = ["NA", ""],
    ) |> DataFrame
first(data, 5)
5×16 DataFrame
RowHospitalIDCityCodeKyukyuKinouSienHyokaDepNeurologyDepNeurosurgeryNumBedsMRINumOwnTeslaPopulationMensekiPopDensityTaxableIncomeMRIOwnDum
Int64Int64Int64?Int64?Int64?Int64?Int64?Int64?Int64?Int64Int64?Int64?Float64?Float64?Int64?Int64
1111011000002431222018946.424743.430171
2211010000001801022018946.424743.430171
3311011000001101122018946.424743.430171
4411011000111343222018946.424743.430171
5511010000002501222018946.424743.430171
dataset = combine(
    groupby(data, :CityCode),
    :MRIOwnDum => sum => :NumMRI,
    [:Population, :Menseki, :PopDensity, :TaxableIncome] .=> mean .=> [:Pop, :Menseki, :PopDen, :Income],   
);
dataset[!, :Pop] = dataset.Pop / 1e+6;
dropmissing!(dataset, :);
numObs = nrow(dataset)
1459

5.2 Bresnahan and Reiss (1991) モデルの推定

hospitalNumCap = 6;
dataset[dataset.NumMRI .> hospitalNumCap, :NumMRI] .= hospitalNumCap;
obj_for_Optim = TwiceDifferentiable(
    x -> calculateBRObjective(x, dataset, hospitalNumCap),
    ones(hospitalNumCap + 1);
    autodiff = :forward
);
@time optim_res = optimize(
    obj_for_Optim,
    zeros(hospitalNumCap + 1),
    repeat([Inf], hospitalNumCap + 1),
    ones(hospitalNumCap + 1),
    Optim.Options(show_trace = false)
);
  5.900208 seconds (15.71 M allocations: 1.961 GiB, 6.81% gc time, 96.10% compilation time)
se = sqrt.(diag(inv(obj_for_Optim.H) ./ numObs));
DataFrame(
    estimates = optim_res.minimizer,
    se = se
)
7×2 DataFrame
Rowestimatesse
Float64Float64
154.62361.52851
233.54331.3618
38.083460.482284
44.236550.326509
52.512150.260241
61.632970.215186
71.390410.046226

5.3 推定値に基づくエクササイズ

alpha_est = optim_res.minimizer[1:hospitalNumCap];
gamma_est = optim_res.minimizer[hospitalNumCap + 1];

EntryThreshold = zeros(Int64, (hospitalNumCap, 2));

deno = alpha_est[1];
EntryThreshold[1,:] .= round(gamma_est / deno .* 1e+6);
for i = 2:hospitalNumCap
    deno = deno - alpha_est[i];
    EntryThreshold[i, :] = round.([gamma_est / deno .* 1e+6, gamma_est / deno .* 1e+6 / i]);
end

EntryThreshold    
6×2 Matrix{Int64}:
  25454  25454
  65958  32979
 106981  35660
 158717  39679
 222532  44506
 301269  50212