Análises: Mato Grosso do Sul
Informações Gerais
Lembre-se de ativar o runtime para
Mix Standalonecom o caminho para/data
Objetivo deste book consiste em apresentar gráficos e tabelas sobre os resultados alcançados com as bases do e-SUS VE, SIPNI e SIVEP do estado de Mato Grosso do Sul.
Municípios de Fronteira
5000906 Antônio João5001243 Aral Moreira5002100 Bela Vista5002803 Caracol5003157 Coronel Sapucaia5003207 Corumbá5004809 Japorã5005202 Ladário5005681 Mundo Novo5006358 Paranhos5006606 Ponta Porã5006903 Porto Murtinho5007703 Sete Quedas
Indicador de Efetividade
$$ EV = \frac{INV-IV}{INV}\ \times 100 $$
- $INV$: Incidência entre os não vacinados
- $IV$: Incidência entre os vacinados
Taxa de Incidência
$$ \frac{C}{P} \times 100000 $$
- $C$: Casos sintomáticos ESUS-VE + SIVEP
- $P$: População residente na faixa etária (ou geral)
Gráficos e Tabelas
Epicurva de taxa de incidência 1
Filtrar:
- Entre 15 e 39 anos
Temporalidade:
- Semana epidemiológica
Gerar um por:
- Por localidade
- Somatório de fronteira
- Somatório de não fronteira
Epicurva de taxa de incidência 2
Temporalidade:
- Semana epidemiológica
Gerar um por:
- Por localidade
- Somatório de fronteira
- Somatório de não fronteira
Epicurva em Gráfico de Área Agrupada
Filtrar:
- Do estado
Temporalidade:
- Semana epidemiológica
Dimensões:
- Vacinados
- Não vacinados
Gerar um por:
- Casos somados
- Internações
- Óbitos
Distribuição em Gráfico de Barra
Filtrar:
- Do estado
Dimensões:
- Vacinados
- Não vacinados
- Por faixa etária
Gerar um por:
- Casos somados
- Internações
- Óbitos
Tabela Indicador de efetividade (Município)
Linhas:
- Município
Colunas:
- casos
- internações
- óbitos
Tabela Indicador de efetividade por faixa etária (Estado)
Linhas:
- Faixa etária
- Todas as idades
- 15 a 39 anos
Colunas:
- casos
- internações
- óbitos
NÃO PRECISA Tabela Indicador de efetividade por vacina (Estado)
Linhas:
- Vacina
Colunas:
- casos
- internações
- óbitos
Identificação dos caminhos
results_dir = Path.expand("sandbox/results", __DIR__)
put_path = fn {map, context}, suffix ->
desired_file =
if suffix == :na do
"#{context}.csv"
else
"#{context}_#{suffix}.csv"
end
results_dir
|> File.ls!()
|> Enum.find(&(&1 =~ desired_file))
|> tap(
&if(
is_nil(&1),
do: raise(~s(Arquivo "*#{desired_file}" não encontrado))
)
)
|> Path.expand(results_dir)
|> then(&{Map.put(map, suffix, &1), context})
end
paths = %{
esus_ve: %{
cases:
{%{}, "esus_ve_cases"}
|> put_path.(:na)
|> put_path.(:no_vaccine)
|> put_path.(:partial_vaccine)
|> put_path.(:full_vaccine)
|> put_path.(:guarded)
|> then(&elem(&1, 0))
},
sipni:
{%{}, "sipni"}
|> put_path.(:partial_vaccine)
|> put_path.(:full_vaccine),
sivep: %{
cases:
{%{}, "sivep_cases"}
|> put_path.(:na)
|> put_path.(:no_vaccine)
|> put_path.(:partial_vaccine)
|> put_path.(:full_vaccine)
|> put_path.(:guarded)
|> then(&elem(&1, 0)),
hospitalizations:
{%{}, "sivep_hospitalizations"}
|> put_path.(:na)
|> put_path.(:no_vaccine)
|> put_path.(:partial_vaccine)
|> put_path.(:full_vaccine)
|> put_path.(:guarded)
|> then(&elem(&1, 0)),
deaths:
{%{}, "sivep_deaths"}
|> put_path.(:na)
|> put_path.(:no_vaccine)
|> put_path.(:partial_vaccine)
|> put_path.(:full_vaccine)
|> put_path.(:guarded)
|> then(&elem(&1, 0))
}
}
Definição de funções e variáveis
defmodule MS do
def create_ets(ets_table) do
:ets.new(ets_table, [:set, :public, :named_table])
rescue
_error -> :ets.delete_all_objects(ets_table)
end
def extract_and_join_csvs(csv_path1, csv_path2, filter, parser, merger) do
data1 = parse_csv(csv_path1, filter, parser)
data2 = parse_csv(csv_path2, filter, parser)
{result, data2} =
Enum.reduce(data1, {[], data2}, fn item1, {result, data2} ->
{item2, data2} = pop_in_list(data2, MS.Filter.same_location_and_date_function(item1))
if is_nil(item2) do
{[item1 | result], data2}
else
{[merger.(item1, item2) | result], data2}
end
end)
data2 ++ result
end
def parse_csv(csv_path, filter, parser) do
csv_path
|> File.read!()
|> NimbleCSV.RFC4180.parse_string()
|> parse_lines(filter, parser)
end
def parse_lines(data, filter, parser) do
if is_list(parser) do
[root_parser | parsers] = parser
data
|> Enum.map(fn line ->
data = root_parser.(line, filter)
unless is_nil(data) do
Enum.reduce(parsers, data, & &1.(&2))
end
end)
|> Enum.reject(&is_nil/1)
else
data
|> Enum.map(&parser.(&1, filter))
|> Enum.reject(&is_nil/1)
end
end
def pop_in_list(list, acc \\ [], fun) do
if Enum.any?(list) do
[item | list] = list
if fun.(item) do
{item, acc ++ list}
else
pop_in_list(list, [item | acc], fun)
end
else
{nil, acc}
end
end
end
defmodule MS.Filter do
def state(map), do: map.location == 50
def before(map, date), do: Date.compare(map.date, date) == :lt
def same_location_and_date_function(map) do
&(&1.location == map.location and Date.compare(&1.date, map.date) == :eq)
end
end
defmodule MS.Merger do
def consolidation_merge(data1, data2, key1, key2, default1, default2) do
{result, data2} =
Enum.reduce(data1, {[], data2}, fn item1, {result, data2} ->
{item2, data2} = MS.pop_in_list(data2, MS.Filter.same_location_and_date_function(item1))
item1 = Map.put(item1, key2, if(is_nil(item2), do: default2, else: item2[key2]))
{[item1 | result], data2}
end)
data2
|> Enum.map(&Map.put(&1, key1, default1))
|> Kernel.++(result)
|> Enum.map(&Map.put(Map.take(&1, [:date, key1, key2]), :date, to_string(&1.date)))
end
def sum_function(key), do: fn m1, m2 -> Map.put(m1, key, m1[key] + m2[key]) end
end
defmodule MS.Locations do
@ets :cities
@csv "sandbox/input/ms_cities_names.csv"
@boundary_cities [
5_000_906,
5_001_243,
5_002_100,
5_002_803,
5_003_157,
5_003_207,
5_004_809,
5_005_202,
5_005_681,
5_006_358,
5_006_606,
5_006_903,
5_007_703
]
def init(path \\ @csv) do
MS.create_ets(@ets)
path
|> Path.expand(__DIR__)
|> File.read!()
|> NimbleCSV.RFC4180.parse_string()
|> Enum.map(fn [k, v] -> {String.to_integer(k), v} end)
|> then(&[{50, "Mato Grosso do Sul"} | &1])
|> then(&:ets.insert(@ets, &1))
:ok
end
def name(id), do: :ets.lookup_element(:cities, id, 2)
def is_boundary_city?(id), do: id in @boundary_cities
end
defmodule MS.Parser do
@keys ~w(a15_29 a30_39 a40_49 a50_59 a60_69 a70_79 a80_plus)a
def age_groups(age_groups) do
age_groups
|> Enum.map(&String.to_integer/1)
|> then(&Enum.zip(@keys, &1))
end
def consolidation([location, date | age_groups], filter) do
item = %{
location: String.to_integer(location),
date: Date.from_iso8601!(date),
age_groups: age_groups(age_groups)
}
if is_nil(filter) do
item
else
if filter.(item) do
item
else
nil
end
end
end
def sum_age_groups_function(key) do
&Map.put(&1, key, Enum.reduce(&1.age_groups, 0, fn {_k, v}, acc -> acc + v end))
end
def sum_age_groups_function(key, take_amount) do
&Map.put(
&1,
key,
Enum.reduce(
Enum.take(&1.age_groups, take_amount),
0,
fn {_k, v}, acc -> acc + v end
)
)
end
end
defmodule MS.Populations do
@ets :populations
@csv "sandbox/input/ms_population.csv"
def init(path \\ @csv) do
MS.create_ets(@ets)
path
|> Path.expand(__DIR__)
|> File.read!()
|> NimbleCSV.RFC4180.parse_string()
|> Enum.map(fn [k, v] -> {String.to_integer(k), String.to_integer(v)} end)
|> then(&:ets.insert(@ets, &1))
:ok
end
def get(id), do: :ets.lookup_element(@ets, id, 2)
end
defmodule MS.PopulationsPerAgeGroup do
@ets :populations_per_age
@csv "sandbox/input/ms_population_per_age.csv"
def init(path \\ @csv) do
MS.create_ets(@ets)
path
|> Path.expand(__DIR__)
|> File.read!()
|> NimbleCSV.RFC4180.parse_string()
|> Enum.map(fn list -> Enum.map(list, &String.to_integer/1) |> to_record() end)
|> then(&:ets.insert(@ets, &1))
:ok
end
defp to_record([
l,
a4,
a9,
a14,
a19,
a24,
a29,
a34,
a39,
a44,
a49,
a54,
a59,
a64,
a69,
a74,
a79,
a80m
]) do
{
l,
a4 + a9 + a14 + a19 + a24 + a29 + a34 + a39,
a4 + a9 + a14 + a19 + a24 + a29,
a34 + a39,
a44 + a49,
a54 + a59,
a64 + a69,
a74 + a79,
a80m
}
end
def get(id, index), do: :ets.lookup_element(@ets, id, index + 2)
def less_than_30(id), do: :ets.lookup_element(@ets, id, 2)
end
:ok
MS.Locations.init()
MS.Populations.init()
MS.PopulationsPerAgeGroup.init()
Epicurva de taxa de incidência 1
defmodule EpicurveIncidenceRate1 do
@title "Epicurva de taxa de incidência"
@label "Taxa de incidência"
def plot(paths) do
%{na: cases1} = paths.esus_ve.cases
%{na: cases2} = paths.sivep.cases
:cases
|> prepare(cases1, cases2)
|> Enum.map(&parse/1)
|> epicurves()
end
defp prepare(key, csv_path1, csv_path2) do
today = Date.utc_today()
MS.extract_and_join_csvs(
csv_path1,
csv_path2,
&MS.Filter.before(&1, today),
[&MS.Parser.consolidation/2, MS.Parser.sum_age_groups_function(key, 2)],
MS.Merger.sum_function(key)
)
end
defp parse(%{cases: cases, location: location} = item) do
population = MS.PopulationsPerAgeGroup.less_than_30(location)
%{
date: to_string(item.date),
location: location,
cases: cases,
population: population,
value: Float.round(cases / population * 100_000, 1)
}
end
def epicurves(data) do
[title: @title]
|> VegaLite.new()
|> VegaLite.concat(
data
|> Enum.group_by(& &1.location)
|> Enum.sort(&(elem(&1, 0) <= elem(&2, 0)))
|> Enum.map(&epicurve/1)
|> append_boundaries(data)
)
end
defp epicurve({location, data}) do
title = if(is_integer(location), do: MS.Locations.name(location), else: location)
[title: title, height: 150, width: 150]
|> VegaLite.new()
|> VegaLite.data_from_values(data)
|> VegaLite.mark(:line, tooltip: true, point: true)
|> VegaLite.encode_field(:x, "date", type: :temporal, time_unit: :yearweek, title: "Data")
|> VegaLite.encode_field(:y, "value", type: :quantitative, aggregate: :mean, title: @label)
end
defp append_boundaries([state | cities], data) do
{boundary, non_boundary} =
Enum.reduce(data, {[], []}, fn item, {boundary, non_boundary} ->
if MS.Locations.is_boundary_city?(item.location) do
{[item | boundary], non_boundary}
else
{boundary, [item | non_boundary]}
end
end)
boundary =
boundary
|> Enum.group_by(& &1.date)
|> Enum.map(&boundary_sum/1)
|> boundary_epicurve("Fronteira")
non_boundary =
non_boundary
|> Enum.group_by(& &1.date)
|> Enum.map(&boundary_sum/1)
|> boundary_epicurve("Não-fronteira")
[state, boundary, non_boundary | cities]
end
defp boundary_sum({date, items}) do
{cases, population} =
Enum.reduce(items, {0, 0}, fn item, {c, p} -> {c + item.cases, p + item.population} end)
%{
date: date,
value: Float.round(cases / population * 100_000, 1)
}
end
defp boundary_epicurve(data, title), do: epicurve({title, data})
end
EpicurveIncidenceRate1.plot(paths)
Epicurva de taxa de incidência 2
defmodule EpicurveIncidenceRate2 do
@title "Epicurva de taxa de incidência"
@label "Taxa de incidência"
def plot(paths) do
%{na: cases1} = paths.esus_ve.cases
%{na: cases2} = paths.sivep.cases
:cases
|> prepare(cases1, cases2)
|> Enum.map(&parse/1)
|> epicurves()
end
defp prepare(key, csv_path1, csv_path2) do
today = Date.utc_today()
MS.extract_and_join_csvs(
csv_path1,
csv_path2,
&MS.Filter.before(&1, today),
[&MS.Parser.consolidation/2, MS.Parser.sum_age_groups_function(key)],
MS.Merger.sum_function(key)
)
end
defp parse(%{cases: cases, location: location} = item) do
population = MS.Populations.get(location)
%{
date: to_string(item.date),
location: location,
cases: cases,
population: population,
value: Float.round(cases / population * 100_000, 1)
}
end
def epicurves(data) do
[title: @title]
|> VegaLite.new()
|> VegaLite.concat(
data
|> Enum.group_by(& &1.location)
|> Enum.sort(&(elem(&1, 0) <= elem(&2, 0)))
|> Enum.map(&epicurve/1)
|> append_boundaries(data)
)
end
defp epicurve({location, data}) do
title = if(is_integer(location), do: MS.Locations.name(location), else: location)
[title: title, height: 150, width: 150]
|> VegaLite.new()
|> VegaLite.data_from_values(data)
|> VegaLite.mark(:line, tooltip: true, point: true)
|> VegaLite.encode_field(:x, "date", type: :temporal, time_unit: :yearweek, title: "Data")
|> VegaLite.encode_field(:y, "value", type: :quantitative, aggregate: :mean, title: @label)
end
defp append_boundaries([state | cities], data) do
{boundary, non_boundary} =
Enum.reduce(data, {[], []}, fn item, {boundary, non_boundary} ->
if MS.Locations.is_boundary_city?(item.location) do
{[item | boundary], non_boundary}
else
{boundary, [item | non_boundary]}
end
end)
boundary =
boundary
|> Enum.group_by(& &1.date)
|> Enum.map(&boundary_sum/1)
|> boundary_epicurve("Fronteira")
non_boundary =
non_boundary
|> Enum.group_by(& &1.date)
|> Enum.map(&boundary_sum/1)
|> boundary_epicurve("Não-fronteira")
[state, boundary, non_boundary | cities]
end
defp boundary_sum({date, items}) do
{cases, population} =
Enum.reduce(items, {0, 0}, fn item, {c, p} -> {c + item.cases, p + item.population} end)
%{
date: date,
value: Float.round(cases / population * 100_000, 1)
}
end
defp boundary_epicurve(data, title), do: epicurve({title, data})
end
EpicurveIncidenceRate2.plot(paths)
Epicurva em Gráfico de Área Agrupada: Casos
defmodule CasesVaccineNoVaccine do
@title "Casos entre vacinados e não vacinados"
@label "Casos"
def plot(paths) do
%{guarded: guarded1, no_vaccine: no_vaccine1} = paths.esus_ve.cases
%{guarded: guarded2, no_vaccine: no_vaccine2} = paths.sivep.cases
guarded =
:guarded
|> prepare(guarded1, guarded2)
|> Enum.map(&%{date: to_string(&1.date), key: "Vacinado", value: &1.guarded})
no_vaccine =
:no_vaccine
|> prepare(no_vaccine1, no_vaccine2)
|> Enum.map(&%{date: to_string(&1.date), key: "Não vacinado", value: &1.no_vaccine})
stacked_area(guarded ++ no_vaccine)
end
defp prepare(key, csv_path1, csv_path2) do
today = Date.utc_today()
MS.extract_and_join_csvs(
csv_path1,
csv_path2,
fn map -> MS.Filter.state(map) and MS.Filter.before(map, today) end,
[&MS.Parser.consolidation/2, MS.Parser.sum_age_groups_function(key)],
MS.Merger.sum_function(key)
)
end
def stacked_area(data) do
[title: @title, width: 600, height: 400]
|> VegaLite.new()
|> VegaLite.data_from_values(data)
|> VegaLite.mark(:area, tooltip: true)
|> VegaLite.encode_field(:x, "date", type: :temporal, time_unit: :yearweek, title: "Data")
|> VegaLite.encode_field(:y, "value", type: :quantitative, aggregate: :mean, title: @label)
|> VegaLite.encode_field(:color, "key", type: :nominal, title: "Tipo")
end
end
CasesVaccineNoVaccine.plot(paths)
Epicurva em Gráfico de Área Agrupada: Internações
defmodule HospitalizationsVaccineNoVaccine do
@title "Internações entre vacinados e não vacinados"
@label "Internações"
def plot(paths) do
%{guarded: guarded, no_vaccine: no_vaccine} = paths.sivep.hospitalizations
guarded =
:guarded
|> prepare(guarded)
|> Enum.map(&%{date: to_string(&1.date), key: "Vacinado", value: &1.guarded})
no_vaccine =
:no_vaccine
|> prepare(no_vaccine)
|> Enum.map(&%{date: to_string(&1.date), key: "Não vacinado", value: &1.no_vaccine})
stacked_area(guarded ++ no_vaccine)
end
defp prepare(key, csv_path) do
today = Date.utc_today()
MS.parse_csv(
csv_path,
fn map -> MS.Filter.state(map) and MS.Filter.before(map, today) end,
parser(key)
)
end
defp stacked_area(data) do
[title: @title, width: 600, height: 400]
|> VegaLite.new()
|> VegaLite.data_from_values(data)
|> VegaLite.mark(:area, tooltip: true)
|> VegaLite.encode_field(:x, "date", type: :temporal, time_unit: :yearweek, title: "Data")
|> VegaLite.encode_field(:y, "value", type: :quantitative, aggregate: :mean, title: @label)
|> VegaLite.encode_field(:color, "key", type: :nominal, title: "Tipo")
end
defp parser(key), do: [&MS.Parser.consolidation/2, MS.Parser.sum_age_groups_function(key)]
end
HospitalizationsVaccineNoVaccine.plot(paths)
Epicurva em Gráfico de Área Agrupada: Óbitos
defmodule DeathsVaccineNoVaccine do
@title "Óbitos entre vacinados e não vacinados"
@label "Óbitos"
def plot(paths) do
%{guarded: guarded, no_vaccine: no_vaccine} = paths.sivep.deaths
guarded =
:guarded
|> prepare(guarded)
|> Enum.map(&%{date: to_string(&1.date), key: "Vacinado", value: &1.guarded})
no_vaccine =
:no_vaccine
|> prepare(no_vaccine)
|> Enum.map(&%{date: to_string(&1.date), key: "Não vacinado", value: &1.no_vaccine})
stacked_area(guarded ++ no_vaccine)
end
defp prepare(key, csv_path) do
today = Date.utc_today()
MS.parse_csv(
csv_path,
fn map -> MS.Filter.state(map) and MS.Filter.before(map, today) end,
parser(key)
)
end
defp stacked_area(data) do
[title: @title, width: 600, height: 400]
|> VegaLite.new()
|> VegaLite.data_from_values(data)
|> VegaLite.mark(:area, tooltip: true)
|> VegaLite.encode_field(:x, "date", type: :temporal, time_unit: :yearweek, title: "Data")
|> VegaLite.encode_field(:y, "value", type: :quantitative, aggregate: :mean, title: @label)
|> VegaLite.encode_field(:color, "key", type: :nominal, title: "Tipo")
end
defp parser(key), do: [&MS.Parser.consolidation/2, MS.Parser.sum_age_groups_function(key)]
end
DeathsVaccineNoVaccine.plot(paths)
Distribuição em Gráfico de Barra: Casos
defmodule CasesVaccineNoVaccineBar do
@title "Casos entre vacinados e não vacinados"
@label "Casos"
def plot(paths) do
%{guarded: guarded1, no_vaccine: no_vaccine1} = paths.esus_ve.cases
%{guarded: guarded2, no_vaccine: no_vaccine2} = paths.sivep.cases
guarded =
guarded1
|> prepare(guarded2)
|> Enum.flat_map(&flat_map/1)
|> sum_age_groups("Vacinado")
no_vaccine =
no_vaccine1
|> prepare(no_vaccine2)
|> Enum.flat_map(&flat_map/1)
|> sum_age_groups("Não-vacinado")
grouped_bar(guarded ++ no_vaccine)
end
defp prepare(csv_path1, csv_path2) do
today = Date.utc_today()
MS.extract_and_join_csvs(
csv_path1,
csv_path2,
fn map -> MS.Filter.state(map) and MS.Filter.before(map, today) end,
&MS.Parser.consolidation/2,
&merge/2
)
end
defp merge(i1, i2) do
i1.age_groups
|> Enum.zip(i2.age_groups)
|> Enum.map(fn {{age_group, v1}, {_, v2}} -> {age_group, v1 + v2} end)
|> then(&Map.put(i1, :age_groups, &1))
end
defp flat_map(item) do
Enum.map(item.age_groups, fn {age_group, value} ->
%{age_group: age_group, value: value}
end)
end
defp sum_age_groups(data, key) do
data
|> Enum.group_by(& &1.age_group)
|> Enum.map(fn {age_group, items} ->
%{key: key, age_group: age_group, value: Enum.reduce(items, 0, &(&1.value + &2))}
end)
|> Enum.sort(&(&1.age_group <= &2.age_group))
end
def grouped_bar(data) do
[title: @title, width: 100, height: 300]
|> VegaLite.new()
|> VegaLite.data_from_values(data)
|> VegaLite.mark(:bar, tooltip: true)
|> VegaLite.encode_field(:column, "age_group", title: "Faixa etária")
|> VegaLite.encode_field(:x, "key", title: "Tipo")
|> VegaLite.encode_field(:color, "key")
|> VegaLite.encode_field(:y, "value", type: :quantitative, title: @label)
end
end
CasesVaccineNoVaccineBar.plot(paths)
Distribuição em Gráfico de Barra: Internações
defmodule HospitalizationsVaccineNoVaccineBar do
@title "Internações entre vacinados e não vacinados"
@label "Internações"
def plot(paths) do
%{guarded: guarded, no_vaccine: no_vaccine} = paths.sivep.hospitalizations
guarded =
guarded
|> prepare()
|> Enum.flat_map(&flat_map/1)
|> sum_age_groups("Vacinado")
no_vaccine =
no_vaccine
|> prepare()
|> Enum.flat_map(&flat_map/1)
|> sum_age_groups("Não-vacinado")
grouped_bar(guarded ++ no_vaccine)
end
defp prepare(csv_path) do
today = Date.utc_today()
MS.parse_csv(
csv_path,
fn map -> MS.Filter.state(map) and MS.Filter.before(map, today) end,
&MS.Parser.consolidation/2
)
end
defp flat_map(item) do
Enum.map(item.age_groups, fn {age_group, value} ->
%{age_group: age_group, value: value}
end)
end
defp sum_age_groups(data, key) do
data
|> Enum.group_by(& &1.age_group)
|> Enum.map(fn {age_group, items} ->
%{key: key, age_group: age_group, value: Enum.reduce(items, 0, &(&1.value + &2))}
end)
|> Enum.sort(&(&1.age_group <= &2.age_group))
end
def grouped_bar(data) do
[title: @title, width: 100, height: 300]
|> VegaLite.new()
|> VegaLite.data_from_values(data)
|> VegaLite.mark(:bar, tooltip: true)
|> VegaLite.encode_field(:column, "age_group", title: "Faixa etária")
|> VegaLite.encode_field(:x, "key", title: "Tipo")
|> VegaLite.encode_field(:color, "key")
|> VegaLite.encode_field(:y, "value", type: :quantitative, title: @label)
end
end
HospitalizationsVaccineNoVaccineBar.plot(paths)
Distribuição em Gráfico de Barra: Óbitos
defmodule DeathsVaccineNoVaccineBar do
@title "Óbitos entre vacinados e não vacinados"
@label "Óbitos"
def plot(paths) do
%{guarded: guarded, no_vaccine: no_vaccine} = paths.sivep.deaths
guarded =
guarded
|> prepare()
|> Enum.flat_map(&flat_map/1)
|> sum_age_groups("Vacinado")
no_vaccine =
no_vaccine
|> prepare()
|> Enum.flat_map(&flat_map/1)
|> sum_age_groups("Não-vacinado")
grouped_bar(guarded ++ no_vaccine)
end
defp prepare(csv_path) do
today = Date.utc_today()
MS.parse_csv(
csv_path,
fn map -> MS.Filter.state(map) and MS.Filter.before(map, today) end,
&MS.Parser.consolidation/2
)
end
defp flat_map(item) do
Enum.map(item.age_groups, fn {age_group, value} ->
%{age_group: age_group, value: value}
end)
end
defp sum_age_groups(data, key) do
data
|> Enum.group_by(& &1.age_group)
|> Enum.map(fn {age_group, items} ->
%{key: key, age_group: age_group, value: Enum.reduce(items, 0, &(&1.value + &2))}
end)
|> Enum.sort(&(&1.age_group <= &2.age_group))
end
def grouped_bar(data) do
[title: @title, width: 100, height: 300]
|> VegaLite.new()
|> VegaLite.data_from_values(data)
|> VegaLite.mark(:bar, tooltip: true)
|> VegaLite.encode_field(:column, "age_group", title: "Faixa etária")
|> VegaLite.encode_field(:x, "key", title: "Tipo")
|> VegaLite.encode_field(:color, "key")
|> VegaLite.encode_field(:y, "value", type: :quantitative, title: @label)
end
end
DeathsVaccineNoVaccineBar.plot(paths)
Tabela indicador de efetividade: Municípios
defmodule EffectivenessIndicatorTableCities do
def show(paths) do
%{guarded: guarded_c1, no_vaccine: no_vaccine_c1} = paths.esus_ve.cases
%{guarded: guarded_c2, no_vaccine: no_vaccine_c2} = paths.sivep.cases
%{guarded: guarded_d, no_vaccine: no_vaccine_d} = paths.sivep.deaths
%{guarded: guarded_h, no_vaccine: no_vaccine_h} = paths.sivep.hospitalizations
guarded_c1
|> prepare_cases(guarded_c2, no_vaccine_c1, no_vaccine_c2)
|> prepare_deaths(guarded_d, no_vaccine_d)
|> prepare_hospitalizations(guarded_h, no_vaccine_h)
|> Enum.map(&Map.put(&1, :location, MS.Locations.name(&1.location)))
|> Enum.sort(&(&1.location <= &2.location))
|> Kino.DataTable.new(keys: [:location, :ev_cases, :ev_hospitalizations, :ev_deaths])
end
defp prepare_cases(guarded1, guarded2, no_vaccine1, no_vaccine2) do
guarded = merge(:guarded, guarded1, guarded2)
no_vaccine = merge(:no_vaccine, no_vaccine1, no_vaccine2)
Enum.group_by(guarded ++ no_vaccine, & &1.location)
|> Enum.map(fn
{location, [i1, i2]} -> %{location: location, ev_cases: ev(Map.merge(i1, i2))}
{location, _items} -> %{location: location, ev_cases: nil}
end)
end
defp merge(key, csv_path1, csv_path2) do
MS.extract_and_join_csvs(
csv_path1,
csv_path2,
fn map -> not MS.Filter.state(map) end,
[&MS.Parser.consolidation/2, MS.Parser.sum_age_groups_function(key)],
MS.Merger.sum_function(key)
)
|> Enum.group_by(& &1.location)
|> Enum.map(fn {location, items} ->
%{:location => location, key => Enum.reduce(items, 0, &(&1[key] + &2))}
end)
end
defp prepare_deaths(data, guarded, no_vaccine) do
Enum.group_by(csv(:guarded, guarded) ++ csv(:no_vaccine, no_vaccine), & &1.location)
|> Enum.map(fn
{location, [i1, i2]} -> %{location: location, ev_deaths: ev(Map.merge(i1, i2))}
{location, _items} -> %{location: location, ev_deaths: nil}
end)
|> Kernel.++(data)
|> Enum.group_by(& &1.location)
|> Enum.map(fn {_location, items} -> Enum.reduce(items, %{}, &Map.merge(&2, &1)) end)
end
defp prepare_hospitalizations(data, guarded, no_vaccine) do
Enum.group_by(csv(:guarded, guarded) ++ csv(:no_vaccine, no_vaccine), & &1.location)
|> Enum.map(fn
{location, [i1, i2]} -> %{location: location, ev_hospitalizations: ev(Map.merge(i1, i2))}
{location, _items} -> %{location: location, ev_hospitalizations: nil}
end)
|> Kernel.++(data)
|> Enum.group_by(& &1.location)
|> Enum.map(fn {_location, items} -> Enum.reduce(items, %{}, &Map.merge(&2, &1)) end)
end
defp csv(key, csv_path) do
MS.parse_csv(
csv_path,
fn map -> not MS.Filter.state(map) end,
[&MS.Parser.consolidation/2, MS.Parser.sum_age_groups_function(key)]
)
|> Enum.group_by(& &1.location)
|> Enum.map(fn {location, items} ->
%{:location => location, key => Enum.reduce(items, 0, &(&1[key] + &2))}
end)
end
defp ev(%{no_vaccine: no_vaccine, guarded: guarded}) do
Float.round((no_vaccine - guarded) / no_vaccine * 100, 1)
end
end
EffectivenessIndicatorTableCities.show(paths)
Tabela indicador de efetividade: Estado
defmodule EffectivenessIndicatorTableState do
def show(paths) do
%{guarded: guarded_c1, no_vaccine: no_vaccine_c1} = paths.esus_ve.cases
%{guarded: guarded_c2, no_vaccine: no_vaccine_c2} = paths.sivep.cases
%{guarded: guarded_d, no_vaccine: no_vaccine_d} = paths.sivep.deaths
%{guarded: guarded_h, no_vaccine: no_vaccine_h} = paths.sivep.hospitalizations
guarded_c1
|> prepare_cases(guarded_c2, no_vaccine_c1, no_vaccine_c2)
|> prepare_deaths(guarded_d, no_vaccine_d)
|> prepare_hospitalizations(guarded_h, no_vaccine_h)
|> Enum.sort(&(&1.age_group <= &2.age_group))
|> Kino.DataTable.new(keys: [:age_group, :ev_cases, :ev_hospitalizations, :ev_deaths])
end
defp prepare_cases(guarded1, guarded2, no_vaccine1, no_vaccine2) do
guarded = merge(:guarded, guarded1, guarded2)
no_vaccine = merge(:no_vaccine, no_vaccine1, no_vaccine2)
Enum.group_by(guarded ++ no_vaccine, & &1.age_group)
|> Enum.map(fn
{age_group, [i1, i2]} -> %{age_group: age_group, ev_cases: ev(Map.merge(i1, i2))}
{age_group, _items} -> %{age_group: age_group, ev_cases: nil}
end)
end
defp merge(key, csv_path1, csv_path2) do
d1 = csv(key, csv_path1)
d2 = csv(key, csv_path2)
d1
|> Kernel.++(d2)
|> Enum.group_by(& &1.age_group)
|> Enum.map(fn {age_group, items} ->
%{
:age_group => age_group,
key => Enum.reduce(items, 0, &(&1[key] + &2))
}
end)
end
defp prepare_deaths(data, guarded, no_vaccine) do
Enum.group_by(csv(:guarded, guarded) ++ csv(:no_vaccine, no_vaccine), & &1.age_group)
|> Enum.map(fn
{age_group, [i1, i2]} -> %{age_group: age_group, ev_deaths: ev(Map.merge(i1, i2))}
{age_group, _items} -> %{age_group: age_group, ev_deaths: nil}
end)
|> Kernel.++(data)
|> Enum.group_by(& &1.age_group)
|> Enum.map(fn {_age_group, items} -> Enum.reduce(items, %{}, &Map.merge(&2, &1)) end)
end
defp prepare_hospitalizations(data, guarded, no_vaccine) do
Enum.group_by(csv(:guarded, guarded) ++ csv(:no_vaccine, no_vaccine), & &1.age_group)
|> Enum.map(fn
{age_group, [i1, i2]} -> %{age_group: age_group, ev_hospitalizations: ev(Map.merge(i1, i2))}
{age_group, _items} -> %{age_group: age_group, ev_hospitalizations: nil}
end)
|> Kernel.++(data)
|> Enum.group_by(& &1.age_group)
|> Enum.map(fn {_age_group, items} -> Enum.reduce(items, %{}, &Map.merge(&2, &1)) end)
end
defp csv(key, csv_path) do
MS.parse_csv(
csv_path,
&MS.Filter.state/1,
&MS.Parser.consolidation/2
)
|> Enum.flat_map(&flat_map(&1, key))
|> Enum.group_by(& &1.age_group)
|> Enum.map(fn {age_group, items} ->
%{:age_group => age_group, key => Enum.reduce(items, 0, &(&1[key] + &2))}
end)
end
defp flat_map(%{age_groups: age_groups}, key) do
data = Enum.map(age_groups, fn {k, v} -> %{:age_group => k, key => v} end)
all = %{:age_group => :all, key => Enum.reduce(data, 0, &(&1[key] + &2))}
a15_39 = %{
:age_group => :a15_39,
key =>
Enum.filter(data, &(&1.age_group in ~w[a15_29 a30_39]a))
|> Enum.reduce(0, &(&1[key] + &2))
}
[all, a15_39 | data]
end
defp ev(%{no_vaccine: no_vaccine, guarded: guarded}) do
Float.round((no_vaccine - guarded) / no_vaccine * 100, 1)
end
end
EffectivenessIndicatorTableState.show(paths)