CNEFE: mudanças entre as edições
mSem resumo de edição |
|||
(16 revisões intermediárias pelo mesmo usuário não estão sendo mostradas) | |||
Linha 2: | Linha 2: | ||
CNEFE - Cadastro Nacional de Endereços para Fins Estatísticos | CNEFE - Cadastro Nacional de Endereços para Fins Estatísticos | ||
Ver https://www.ibge.gov.br/estatisticas/sociais/populacao/38734-cadastro-nacional-de-enderecos-para-fins-estatisticos.html?edicao=40122&t=resultados | Ver [https://www.ibge.gov.br/estatisticas/sociais/populacao/38734-cadastro-nacional-de-enderecos-para-fins-estatisticos.html?edicao=40122&t=resultados página oficial do IBGE/CNEFE]. | ||
Para a visualização em diferentes mapas de fundo, ver https://gis.stackexchange.com/a/217670/7505 | |||
Pendente revisar e simplificar passo a passo. | |||
Ver também [[CNEFE/Pontos basicos]] para tratamento global final OpenAddresses | |||
PS: o nome do aparelho de coleta de dados do Cernso é [https://agenciadenoticias.ibge.gov.br/agencia-noticias/2012-agencia-de-noticias/noticias/33487-com-distribuicao-avancada-ibge-esta-perto-de-concluir-preparacao-dos-dispositivos-de-coleta-do-censo-2022 Dispositivo Móvel de Coleta (DMC)] (repassado para o Ministério da Saúde). | |||
== Faces de Quadra == | == Faces de Quadra == | ||
Pegar em 4314902_faces_de_logradouros_2021.prj | Pegar em 4314902_faces_de_logradouros_2021.prj o SRID da projeção usada. | ||
Fonte em [https://www.ibge.gov.br/geociencias/organizacao-do-territorio/malhas-territoriais/28971-base-de-faces-de-logradouros-dobrasil.html?=&t=acesso-ao-produto IBGE/base faces de quadra/acesso ao produto]. Descritivo em [https://www.ibge.gov.br/geociencias/organizacao-do-territorio/malhas-territoriais/28971-base-de-faces-de-logradouros-dobrasil.html?=&t=sobre Sobre a publicação]. [https://www.youtube.com/watch?v=aFluEBKXTCs aula do IBGE para os agentes usando celular]. [https://www.youtube.com/watch?v=rDAQ1Du9pa4 Mais uma boa aula Tanaka]. | |||
Para POA utilizamos esses originais, com download de maio de 2024: | |||
<pre> | |||
3ad3031f5503a4404af825262ee8232cc04d4ea6683d42c5dd0a2f2a27ac9824 4314902_faces_de_logradouros_2021.cpg | |||
e55572718b6bc70f3f32bc58c81cecaf48aa1aebeec313ae20e567e81f3d235d 4314902_faces_de_logradouros_2021.dbf | |||
c9b61f7c5c0d268153118af4183b06d943c1652e94e1201f513a6dcf0ab06567 4314902_faces_de_logradouros_2021.prj | |||
de05db0b048dab811c900c28f6bde2c77f9e3d277011c03801390d20ef838a51 4314902_faces_de_logradouros_2021.shp | |||
2c83a1e2f6c69e1ea331d59166dc2ff612206e42e7511a5bddc2d1fe2df9d07f 4314902_faces_de_logradouros_2021.shx | |||
</pre> | |||
Falta conferir se usamos mesmo a fonte mais atual no DL Digital-guard. Conferir com https://www.ibge.gov.br/geociencias/organizacao-do-territorio/malhas-territoriais/28971-base-de-faces-de-logradouros-do-brasil.html | |||
Resumo das explicações [https://www.ibge.gov.br/geociencias/organizacao-do-territorio/malhas-territoriais/28971-base-de-faces-de-logradouros-do-brasil.html?=&t=sobre na aba "Sobre"]. | |||
<pre> | <pre> | ||
Linha 27: | Linha 49: | ||
----- | ----- | ||
shp2pgsql log | psql -q postgres://postgres@localhost/poa | shp2pgsql log | psql -q postgres://postgres@localhost/poa | ||
</pre> | |||
Melhorando os dados: | |||
<pre> | |||
drop view if exists vw01_log ; | |||
create view vw01_log as select *, regexp_replace( coalesce(nm_tip_log,'') || ' '|| coalesce(nm_tit_log,'') ||' '|| coalesce(nm_log,''), '\s+', ' ', 'g') as via_name from log; | |||
select gid, cd_setor, cd_quadra, cd_face, via_name, tot_res from vw01_log limit 100; | |||
</pre> | </pre> | ||
Linha 32: | Linha 62: | ||
Por cidade temos [https://www.ibge.gov.br/estatisticas/downloads-estatisticas.html?caminho=Cadastro_Nacional_de_Enderecos_para_Fins_Estatisticos/Censo_Demografico_2022/Arquivos_CNEFE/Municipio Censo_Demografico_2022/Arquivos_CNEFE/Municipio], direto latLong em srid=4326. | Por cidade temos [https://www.ibge.gov.br/estatisticas/downloads-estatisticas.html?caminho=Cadastro_Nacional_de_Enderecos_para_Fins_Estatisticos/Censo_Demografico_2022/Arquivos_CNEFE/Municipio Censo_Demografico_2022/Arquivos_CNEFE/Municipio], direto latLong em srid=4326. | ||
Pelo cabeçalho podemos copiar para uma tabela texto, | Esta [https://www.ibge.gov.br/estatisticas/sociais/populacao/38734-cadastro-nacional-de-enderecos-para-fins-estatisticos.html?edicao=40122&t=resultados página dá acesso ao Excel de descrição, "Dicionário"]. Pelo cabeçalho podemos copiar para uma tabela texto, depois testar se a algumas converções de tipo são válidas. | ||
<pre> | <pre> | ||
Linha 63: | Linha 93: | ||
LATITUDE real, | LATITUDE real, | ||
LONGITUDE real, | LONGITUDE real, | ||
NV_GEO_COORD text, | NV_GEO_COORD text, -- nivel de confiança na coordenada | ||
COD_ESPECIE text, | COD_ESPECIE text, | ||
DSC_ESTABELECIMENTO text, | DSC_ESTABELECIMENTO text, | ||
Linha 72: | Linha 102: | ||
); | ); | ||
copy ibge_cnefe2022 from '/tmp/POA_FACES/4314902_PORTO_ALEGRE.csv' with (format CSV, delimiter ';', header); | copy ibge_cnefe2022 from '/tmp/POA_FACES/4314902_PORTO_ALEGRE.csv' with (format CSV, delimiter ';', header); | ||
---- | |||
drop view if exists vw02_ibge_cnefe2022; | |||
create view vw02_ibge_cnefe2022 as | |||
select *, ST_GeoHash(geom,9) as ghs9, ST_GeoHash(geom,10) as ghs10 | |||
from ( | |||
select *, regexp_replace( coalesce(nom_tipo_seglogr,'') ||' '|| coalesce(nom_titulo_seglogr,'') ||' '|| coalesce(nom_seglogr,''), '\s+',' ','g') as via_name, | |||
ST_SetSRID(ST_MakePoint(longitude::float, latitude::float),4326) as geom | |||
from ibge_cnefe2022 | |||
) t | |||
; | |||
-- teste de hipotese de ponto e endereço únicos: | |||
-- select count(*) from (select distinct ghs9, cod_setor, num_quadra, num_face, via_name, num_endereco from vw02_ibge_cnefe2022) t; -- 379957. -- same where geom is not null and via_name>'' and num_endereco>'' ) t; | |||
-- select 379957.0/762239; -- 49,847% = 50% | |||
</pre> | |||
Avaliação pelo qualificador do IBGE, nv_geo_coord: | |||
<pre> | |||
-- Por domicílio | |||
with t as (select count(*) as nt from ibge_cnefe2022) select nv_geo_coord, count(*) n, round(100.0*count(*)/t.nt,2)::text||'%' as perc from t,vw02_ibge_cnefe2022 group by 1,nt order by 1; | |||
</pre> | |||
Os dois primeiros são válidos, os demais podem ser descartados: | |||
=== Contagens gerais === | |||
<pre> | |||
select count(*) n_dist from (select distinct * from ibge_cnefe2022) t | |||
; -- 762239 | |||
select count(*) n, count(distinct cod_unico_endereco) n_cod_uend, count(distinct ghs) n_ghs, | |||
count(distinct latitude||','||longitude) n_latlon | |||
from vw02_ibge_cnefe2022 | |||
; -- 762239 | 757512 | 350635 | 389028 | |||
select avg(n) avg, stddev_pop(n) dev, count(*) tmultiplos, sum(n) as tot from ( | |||
select cod_unico_endereco, count(*) n from ibge_cnefe2022 group by 1 having count(*)>1 | |||
) t; -- 2.0045 | 0.07 | 4706 | 9433. Conclusão: 2.01±0.07 , maioria dos 9433 com 1 duplicidade. | |||
select count(*) n_ghs9_nv from (select distinct nv_geo_coord, ghs9 from vw02_ibge_cnefe2022) t | |||
; -- 358000 | |||
select count(*) n_ghs10_nv from (select distinct nv_geo_coord, ghs10 from vw02_ibge_cnefe2022) t | |||
; -- 393565 | |||
select sqrt(avg(st_area(ST_GeomFromGeoHash(ghs9),true))) as ghs9_precisao, | |||
sqrt(avg(st_area(ST_GeomFromGeoHash(ghs10),true))) as ghs10_precisao | |||
from vw02_ibge_cnefe2022 | |||
; -- ghs9_precisao = 4.437 ~ 5 metros de precisão no Geohash de 9 dígitos. | |||
-- ghs10_precisao = 0.7844 ~ 1 metro no Geohash de 10 dígitos. | |||
-- select round(100.0*x/762239) perc_x_of_n; | |||
select compl1, count(*) n_casos FROM ( | |||
select ghs9, array_agg(distinct nom_comp_elem1) compl1 from vw02_ibge_cnefe2022 group by 1 having count(*)>1 | |||
) t group by 1 order by 2 desc, 1; | |||
select compl, count(*) n_casos FROM ( | |||
select ghs10, array_agg(distinct coalesce(nom_comp_elem1,'')||coalesce(' '||nom_comp_elem2,'')) compl from vw02_ibge_cnefe2022 group by 1 having count(*)>1 | |||
) t group by 1 order by 2 desc, 1limit 10; | |||
compl | n_casos | |||
-----------------------+--------- | |||
{APARTAMENTO} | 15620 | |||
{""} | 6945 | |||
{CASA} | 5642 | |||
{FRENTE,FUNDOS} | 4616 | |||
{"BLOCO APARTAMENTO"} | 3694 | |||
{"",FUNDOS} | 1285 | |||
{"",CASA} | 1231 | |||
{FUNDOS} | 877 | |||
{SOBRADO,TERREO} | 821 | |||
{"",FRENTE} | 349 | |||
total | 41080 = 5.4% de 762239; ou 10.6% de 389028. | |||
</pre> | |||
{|class="wikitable"| | |||
|- | |||
!Rótulo !! select count(''criterio''?)<br/>from ibge_cnefe2022!! n_doms !! perc ''n'' | |||
|- | |||
|''n''<br/>= n_dist|| <code>*</code> || 762239 || 100% | |||
|- | |||
|''n_cod_uend''|| <code>distinct cod_unico_endereco</code> || 757512 || 99.4% | |||
|- | |||
|''n_latlon''|| <code><nowiki>distinct latitude||','||longitude</nowiki></code>||389028 || 51% | |||
|- | |||
|''n_ghs10'' || <code>distinct ghs10</code>||386857 || 51% | |||
|- | |||
|''n_ghs9'' || <code>distinct ghs9</code>||350635 || 46% | |||
|} | |||
Conclusões sobre o perfil de algumas contagens: | |||
* Identificadores únicos: era esperada a unicidade em 100% dos registros, ou seja, que ''n''=''n_cod_uend''. Houve, todavia, uma diferença de 0,6% (100% - 99,4%), devido a casos de repetição. O valor de contagens superiores a 1 resultou em média de 2,01±0,07; portanto maioria dos 9433 identificadores problemáticos tem apenas mais 1 outro domicílio apresentando mesmo identificador. | |||
* A contagem de ''n_latlon'', com apenas 51% ao invés de 100%, mostra a intensão do IBGE em incluir nos registros os casos de endereço horizontais iguais porém com complemento diferenciando, o que se confirma pelas contagens no perfil dos complementos (vide amostragem ''compl1'' e ''compl2'' em ~11% dos casos de ''n_latlon''). A rigor o IBGE registrou "endereços domicíliares", não apenas "endereços de rua". Neste relatório denominaremos o primeiro de domicílio ('''dom''') e o segundo de endereço de fato ('''end''') ou ponto. | |||
* A escolha entre Geohashes de 9 ou 10 metros dependeria da precisão média dos pontos do IBGE. Como demonstra a nuvem de pontos, é bastante | |||
* A contagem de ''n_ghs9'' fez uso de Geohashes de 9 dígitos, garantindo a precisão da ordem de 5 metros, ou seja, superior ao erro de GPS da núvem de pontos. A contagem ''n_ghs9'' resultou em 46%, bem longe dos 51% de ''n_latlon'', gerando talvez duplicidade maior do que esperada. Como a precisão é variável (depende dos satélites GPS e do [https://www.youtube.com/watch?v=AVW40YB3v2s tempo de espera do agente]), sugere-se usar ''ghs10'' ou manter o ponto original e só depois do translado para a face de quadra (que aumenta a precisão) fazer a contagem de Geohashes ''ghs10''. | |||
{|class="wikitable"| | |||
|- | |||
! nv_geo_coord !! n_doms !! perc | |||
|- | |||
| 1 = Endereço - coordenada original do Censo 2022 || 630603 || 82.73% | |||
|- | |||
| 2 = Endereço - coordenada modificada (apartamentos em um mesmo número no logradouro). || 119942 || 15.74% | |||
|- | |||
| 3 = Endereço - coordenada estimada (endereços originalmente sem coordenadas ou coordenadas inválidas). || 8900 || 1.17% | |||
|- | |||
| 4 = Face de quadra. || 2753 || 0.36% | |||
|- | |||
| 5 = Localidade || 4 || 0.00% | |||
|- | |||
| 6 = Setor censitário || 37 || 0.00% | |||
|} | |||
<pre> | |||
-- por pontos únicos em ghs9 | |||
with t as (select count(distinct ghs9||nv_geo_coord) ntpt from vw02_ibge_cnefe2022) select nv_geo_coord, count(distinct ghs9) n_ghs9s, round(100.0*count(distinct ghs9)/t.ntpt,2)::text||'%' as perc from t,vw02_ibge_cnefe2022 group by 1,ntpt order by 1; | |||
</pre> | |||
{|class="wikitable"| | |||
|- | |||
! nv_geo_coord !! n_ghs9s !! perc | |||
|- | |||
| 1 = Endereço - coordenada original do Censo 2022 || 343098 || 95.84% | |||
|- | |||
| 2 = Endereço - coordenada modificada (apartamentos em um mesmo número no logradouro). || 11224 || 3.14% | |||
|- | |||
| 3 = Endereço - coordenada estimada (endereços originalmente sem coordenadas ou coordenadas inválidas). || 2865 || 0.80% | |||
|- | |||
| 4 = Face de quadra. || 798 || 0.22% | |||
|- | |||
| 5 = Localidade || 3 || 0.00% | |||
|- | |||
| 6 = Setor censitário || 12 || 0.00% | |||
|} | |||
Conclusão: como queremos filtrar até o nível de pontos únicos, há garantia de 99,9% dos endereços em condição adequada (tipos 1 ou 2). | |||
=== Filtragens === | |||
As filtragens seguem o seguinte passo a passo: | |||
* Unicidade de endereço: DISTINCT cod_setor, cep, via_name, num_endereco | |||
* Unicidade de posição: DISTINCT ghs | |||
* Filtrando unicidades: primeiro de endereço, porém incluindo array de geohashes distintos. Se forem vizinhos não possuem mesmo prefixo conferir maior distancia entre eles. | |||
<pre> | |||
CREATE FUNCTION hcodes_sameparent(g text[]) RETURNS boolean AS $f$ | |||
SELECT bool_and( CASE | |||
WHEN l1=l2 THEN substr(g1,1,l1-1)=substr(g2,1,l2-1) | |||
WHEN l1>l2 THEN g1 ~ ('^'||g2) -- WHEN l1=l2+1 | |||
ELSE g2 ~ ('^'||g1) -- WHEN l2=l1+1 ELSE false | |||
END ) | |||
FROM ( | |||
select g1, g2, length(g1) l1, length(g2) l2 | |||
from unnest(g) WITH ORDINALITY AS a(g1,i1) | |||
inner join unnest(g) WITH ORDINALITY AS b(g2,i2) | |||
on i1<i2 | |||
) t1 | |||
$f$ LANGUAGE SQL; | |||
CREATE FUNCTION geoms_maxdist(g geometry[], use_spheroid boolean default false) RETURNS float AS $f$ | |||
SELECT MAX( ST_Distance(g1,g2,use_spheroid) ) | |||
FROM unnest(g) WITH ORDINALITY AS a(g1,i1) | |||
INNER JOIN unnest(g) WITH ORDINALITY AS b(g2,i2) | |||
ON i1<i2 | |||
$f$ LANGUAGE SQL; | |||
create table tmp_ibge_cnefe2022_uniq1 AS -- unicidade básica, ainda com repetição de pontos | |||
SELECT DISTINCT ghs, via_name, num_endereco | |||
FROM vw02_ibge_cnefe2022 | |||
; -- 379228 de 762239 = select round(100.0*379228.0/762239); = 50% | |||
select avg(n) from (select ghs, count(*) n from ibge_cnefe2022_uniq1 group by 1) t | |||
where n=1 -- n>1 | |||
; | |||
-- 325993 não-duplicados mais 2.16*24642 duplicados = 325993+2.16*24642 = 379220 ~ 379228. | |||
</pre> | |||
Só na redução de pontos para 50% já é bem drástica, provavelmente inclui casos que diferenciam apenas no complemento. | |||
Desses, com duplicidade posicional apenas ~7,6% (24642 de 325993), sendo também razoável o seu descarte de tmp_ibge_cnefe2022_uniq1. | |||
<pre> | |||
drop table if exists ibge_cnefe2022_uniq2; | |||
create table ibge_cnefe2022_uniq2 AS -- remove endereços duplicados em locais diferentes | |||
select v.cod_setor, v.num_quadra, v.num_face, v.cep, v.via_name, v.num_endereco, | |||
array_agg(v.ghs) ghss, array_agg(v.geom) geoms | |||
from( | |||
SELECT DISTINCT ON (ghs) ghs, via_name, num_endereco, count(*) OVER (PARTITION BY ghs) AS ghs_count | |||
FROM tmp_ibge_cnefe2022_uniq1 | |||
) g -- 325993 | |||
INNER JOIN vw02_ibge_cnefe2022 v ON 1=g.ghs_count AND g.ghs=v.ghs | |||
group by 1,2,3,4,5,6 | |||
order by 1,2,3,4,5,6 | |||
; -- 257387 | |||
select count(*) from (select cep, via_name, num_endereco, hcodes_sameparent(ghss) as is_same from ibge_cnefe2022_uniq2 where cardinality(ghss)>1 ) where is_same;-- 49597 | |||
select count(*) from (select cep, via_name, num_endereco, hcodes_sameparent(ghss) as is_same from ibge_cnefe2022_uniq2 where cardinality(ghss)>1 ) where not(is_same); -- 22523 | |||
-- conclusão: vale a pena manter o same, removendo o último dígito, fornecendo um booleano para usuário decidir se valido ou não. | |||
-- os casos de não same podem ser resgatados por geometria | |||
select count(*), avg(dist) from (select geoms_maxdist(geoms,true) dist from (select cep, via_name, num_endereco, hcodes_sameparent(ghss) as is_same, geoms from ibge_cnefe2022_uniq2 where cardinality(ghss)>1 ) where not(is_same)) where dist<=20; | |||
-- 12193 | |||
select count(*), avg(dist) from (select geoms_maxdist(geoms,true) dist from (select cep, via_name, num_endereco, hcodes_sameparent(ghss) as is_same, geoms from ibge_cnefe2022_uniq2 where cardinality(ghss)>1 ) where not(is_same)) where dist<=5; | |||
-- 1848 (não compensa) | |||
select count(*), avg(dist) from (select geoms_maxdist(geoms,true) dist from (select cep, via_name, num_endereco, hcodes_sameparent(ghss) as is_same, geoms from ibge_cnefe2022_uniq2 where cardinality(ghss)>1 ) t2 where is_same) t3 | |||
-- 49597 | 2.67 (ok distancia pequena e numero expressivo) | |||
select count(*), count(distinct via_name||num_endereco) from (select distinct cod_setor, via_name, num_endereco, cep | |||
from vw02_ibge_cnefe2022 | |||
) t; -- 288685 | 277160 | |||
</pre> | |||
== Tratamentos finais == | |||
<pre> | |||
drop table ibge_cnefe2022_uniq3; | |||
CREATE TABLE ibge_cnefe2022_uniq3 AS | |||
SELECT ghss[1] as ghs, cod_setor, num_quadra::int as num_quadra, num_face::int num_face, | |||
cep, via_name, num_endereco, | |||
false AS is_centroid | |||
FROM ibge_cnefe2022_uniq2 WHERE cardinality(ghss)=1 | |||
UNION ALL | |||
SELECT st_geohash(geoms_centroid(geoms),9) as ghs, | |||
cod_setor, num_quadra::int, num_face::int, cep, via_name, num_endereco, | |||
true AS is_centroid | |||
FROM ibge_cnefe2022_uniq2 | |||
WHERE cardinality(ghss)>1 | |||
AND (hcodes_sameparent(ghss) OR (geoms_maxdist(geoms,true))[2]<=20) | |||
ORDER BY 1 | |||
; -- 249834 | |||
---- | |||
copy ibge_cnefe2022_uniq3 to '/tmp/BR-RS-POA2024_CNEFE-ptsEnderecoUnico.csv' CSV HEADER; | |||
copy (select gid, cd_setor, cd_quadra::int as cd_quadra, cd_face::int as cd_face, via_name, tot_res, geom FROM vw01_log) TO '/tmp/BR-RS-POA-faces.csv' CSV HEADER; | |||
-- COPY 56645 | |||
--- CONTAGENS DE JOIN | |||
With f AS( | |||
SELECT gid, cd_setor, cd_quadra::int as cd_quadra, cd_face::int as cd_face, | |||
via_name, tot_res, st_geohash(geom,7) as ghs7 | |||
FROM vw01_log | |||
) | |||
SELECT count(*) | |||
FROM ibge_cnefe2022_uniq3 u INNER JOIN f | |||
ON substring(u.cod_setor,1,15)!=f.cd_setor AND substring(u.ghs,1,7)=f.ghs7 AND f.cd_quadra=u.num_quadra AND f.cd_face=u.num_face AND f.via_name=u.via_name | |||
; -- 5893 | |||
-- testar se são consistentes ON substring(u.ghs,1,7)=f.ghs7 AND f.cd_quadra=u.num_quadra AND f.cd_face=u.num_face AND f.via_name=u.via_name | |||
------- final só confiaveis: | |||
drop table ibge_cnefe2022_uniq_onface; | |||
create table ibge_cnefe2022_uniq_onface AS | |||
WITH f AS ( | |||
SELECT gid, cd_setor, cd_quadra::int as cd_quadra, cd_face::int as cd_face, | |||
via_name, tot_res, st_geohash(geom,7) as ghs7, geom | |||
FROM vw01_log | |||
) | |||
SELECT u.ghs, u.cep, u.via_name, u.num_endereco, u.is_centroid, substring(u.ghs,1,7)=f.ghs7 as is_nearface, | |||
ST_ClosestPoint(f.geom, ST_PointFromGeoHash(u.ghs)) as geom | |||
FROM ibge_cnefe2022_uniq3 u INNER JOIN f | |||
ON substring(u.cod_setor,1,15)=f.cd_setor AND f.cd_quadra=u.num_quadra AND f.cd_face=u.num_face AND f.via_name=u.via_name | |||
order by 1 | |||
; -- 198797 | |||
</pre> | </pre> |
Edição atual tal como às 16h12min de 8 de setembro de 2024
CNEFE - Cadastro Nacional de Endereços para Fins Estatísticos
Ver página oficial do IBGE/CNEFE.
Para a visualização em diferentes mapas de fundo, ver https://gis.stackexchange.com/a/217670/7505
Pendente revisar e simplificar passo a passo.
Ver também CNEFE/Pontos basicos para tratamento global final OpenAddresses
PS: o nome do aparelho de coleta de dados do Cernso é Dispositivo Móvel de Coleta (DMC) (repassado para o Ministério da Saúde).
Faces de Quadra
Pegar em 4314902_faces_de_logradouros_2021.prj o SRID da projeção usada.
Fonte em IBGE/base faces de quadra/acesso ao produto. Descritivo em Sobre a publicação. aula do IBGE para os agentes usando celular. Mais uma boa aula Tanaka.
Para POA utilizamos esses originais, com download de maio de 2024:
3ad3031f5503a4404af825262ee8232cc04d4ea6683d42c5dd0a2f2a27ac9824 4314902_faces_de_logradouros_2021.cpg e55572718b6bc70f3f32bc58c81cecaf48aa1aebeec313ae20e567e81f3d235d 4314902_faces_de_logradouros_2021.dbf c9b61f7c5c0d268153118af4183b06d943c1652e94e1201f513a6dcf0ab06567 4314902_faces_de_logradouros_2021.prj de05db0b048dab811c900c28f6bde2c77f9e3d277011c03801390d20ef838a51 4314902_faces_de_logradouros_2021.shp 2c83a1e2f6c69e1ea331d59166dc2ff612206e42e7511a5bddc2d1fe2df9d07f 4314902_faces_de_logradouros_2021.shx
Falta conferir se usamos mesmo a fonte mais atual no DL Digital-guard. Conferir com https://www.ibge.gov.br/geociencias/organizacao-do-territorio/malhas-territoriais/28971-base-de-faces-de-logradouros-do-brasil.html Resumo das explicações na aba "Sobre".
mkdir /tmp/POA_FACES/ cd /tmp/POA_FACES wget https://dl.digital-guard.org/5d5daa06e048ad8c83c909babee040e26fd8a54a29ed4cef2d2d220a3bd17b84.zip zip -T 5d5daa06e048ad8c83c909babee040e26fd8a54a29ed4cef2d2d220a3bd17b84.zip cd '/tmp/5d5daa06e048ad8c83c909babee040e26fd8a54a29ed4cef2d2d220a3bd17b84/rs_faces_de_logradouros_2021/' cp 4314902* /tmp/POA_FACES
Supor arquivos logradouro em log:
create database poa; \c poa create extension postgis; ----- shp2pgsql log | psql -q postgres://postgres@localhost/poa
Melhorando os dados:
drop view if exists vw01_log ; create view vw01_log as select *, regexp_replace( coalesce(nm_tip_log,'') || ' '|| coalesce(nm_tit_log,'') ||' '|| coalesce(nm_log,''), '\s+', ' ', 'g') as via_name from log; select gid, cd_setor, cd_quadra, cd_face, via_name, tot_res from vw01_log limit 100;
Pontos
Por cidade temos Censo_Demografico_2022/Arquivos_CNEFE/Municipio, direto latLong em srid=4326.
Esta página dá acesso ao Excel de descrição, "Dicionário". Pelo cabeçalho podemos copiar para uma tabela texto, depois testar se a algumas converções de tipo são válidas.
CREATE TABLE ibge_cnefe2022 ( COD_UNICO_ENDERECO text, COD_UF text, COD_MUNICIPIO text, COD_DISTRITO text, COD_SUBDISTRITO text, COD_SETOR text, NUM_QUADRA text, NUM_FACE text, CEP text, DSC_LOCALIDADE text, NOM_TIPO_SEGLOGR text, NOM_TITULO_SEGLOGR text, NOM_SEGLOGR text, NUM_ENDERECO text, DSC_MODIFICADOR text, NOM_COMP_ELEM1 text, VAL_COMP_ELEM1 text, NOM_COMP_ELEM2 text, VAL_COMP_ELEM2 text, NOM_COMP_ELEM3 text, VAL_COMP_ELEM3 text, NOM_COMP_ELEM4 text, VAL_COMP_ELEM4 text, NOM_COMP_ELEM5 text, VAL_COMP_ELEM5 text, LATITUDE real, LONGITUDE real, NV_GEO_COORD text, -- nivel de confiança na coordenada COD_ESPECIE text, DSC_ESTABELECIMENTO text, COD_INDICADOR_ESTAB_ENDERECO text, COD_INDICADOR_CONST_ENDERECO text, COD_INDICADOR_FINALIDADE_CONST text, COD_TIPO_ESPECI text ); copy ibge_cnefe2022 from '/tmp/POA_FACES/4314902_PORTO_ALEGRE.csv' with (format CSV, delimiter ';', header); ---- drop view if exists vw02_ibge_cnefe2022; create view vw02_ibge_cnefe2022 as select *, ST_GeoHash(geom,9) as ghs9, ST_GeoHash(geom,10) as ghs10 from ( select *, regexp_replace( coalesce(nom_tipo_seglogr,'') ||' '|| coalesce(nom_titulo_seglogr,'') ||' '|| coalesce(nom_seglogr,''), '\s+',' ','g') as via_name, ST_SetSRID(ST_MakePoint(longitude::float, latitude::float),4326) as geom from ibge_cnefe2022 ) t ; -- teste de hipotese de ponto e endereço únicos: -- select count(*) from (select distinct ghs9, cod_setor, num_quadra, num_face, via_name, num_endereco from vw02_ibge_cnefe2022) t; -- 379957. -- same where geom is not null and via_name>'' and num_endereco>'' ) t; -- select 379957.0/762239; -- 49,847% = 50%
Avaliação pelo qualificador do IBGE, nv_geo_coord:
-- Por domicílio with t as (select count(*) as nt from ibge_cnefe2022) select nv_geo_coord, count(*) n, round(100.0*count(*)/t.nt,2)::text||'%' as perc from t,vw02_ibge_cnefe2022 group by 1,nt order by 1;
Os dois primeiros são válidos, os demais podem ser descartados:
Contagens gerais
select count(*) n_dist from (select distinct * from ibge_cnefe2022) t ; -- 762239 select count(*) n, count(distinct cod_unico_endereco) n_cod_uend, count(distinct ghs) n_ghs, count(distinct latitude||','||longitude) n_latlon from vw02_ibge_cnefe2022 ; -- 762239 | 757512 | 350635 | 389028 select avg(n) avg, stddev_pop(n) dev, count(*) tmultiplos, sum(n) as tot from ( select cod_unico_endereco, count(*) n from ibge_cnefe2022 group by 1 having count(*)>1 ) t; -- 2.0045 | 0.07 | 4706 | 9433. Conclusão: 2.01±0.07 , maioria dos 9433 com 1 duplicidade. select count(*) n_ghs9_nv from (select distinct nv_geo_coord, ghs9 from vw02_ibge_cnefe2022) t ; -- 358000 select count(*) n_ghs10_nv from (select distinct nv_geo_coord, ghs10 from vw02_ibge_cnefe2022) t ; -- 393565 select sqrt(avg(st_area(ST_GeomFromGeoHash(ghs9),true))) as ghs9_precisao, sqrt(avg(st_area(ST_GeomFromGeoHash(ghs10),true))) as ghs10_precisao from vw02_ibge_cnefe2022 ; -- ghs9_precisao = 4.437 ~ 5 metros de precisão no Geohash de 9 dígitos. -- ghs10_precisao = 0.7844 ~ 1 metro no Geohash de 10 dígitos. -- select round(100.0*x/762239) perc_x_of_n; select compl1, count(*) n_casos FROM ( select ghs9, array_agg(distinct nom_comp_elem1) compl1 from vw02_ibge_cnefe2022 group by 1 having count(*)>1 ) t group by 1 order by 2 desc, 1; select compl, count(*) n_casos FROM ( select ghs10, array_agg(distinct coalesce(nom_comp_elem1,'')||coalesce(' '||nom_comp_elem2,'')) compl from vw02_ibge_cnefe2022 group by 1 having count(*)>1 ) t group by 1 order by 2 desc, 1limit 10; compl | n_casos -----------------------+--------- {APARTAMENTO} | 15620 {""} | 6945 {CASA} | 5642 {FRENTE,FUNDOS} | 4616 {"BLOCO APARTAMENTO"} | 3694 {"",FUNDOS} | 1285 {"",CASA} | 1231 {FUNDOS} | 877 {SOBRADO,TERREO} | 821 {"",FRENTE} | 349 total | 41080 = 5.4% de 762239; ou 10.6% de 389028.
Rótulo | select count(criterio?) from ibge_cnefe2022 |
n_doms | perc n |
---|---|---|---|
n = n_dist |
* |
762239 | 100% |
n_cod_uend | distinct cod_unico_endereco |
757512 | 99.4% |
n_latlon | distinct latitude||','||longitude |
389028 | 51% |
n_ghs10 | distinct ghs10 |
386857 | 51% |
n_ghs9 | distinct ghs9 |
350635 | 46% |
Conclusões sobre o perfil de algumas contagens:
- Identificadores únicos: era esperada a unicidade em 100% dos registros, ou seja, que n=n_cod_uend. Houve, todavia, uma diferença de 0,6% (100% - 99,4%), devido a casos de repetição. O valor de contagens superiores a 1 resultou em média de 2,01±0,07; portanto maioria dos 9433 identificadores problemáticos tem apenas mais 1 outro domicílio apresentando mesmo identificador.
- A contagem de n_latlon, com apenas 51% ao invés de 100%, mostra a intensão do IBGE em incluir nos registros os casos de endereço horizontais iguais porém com complemento diferenciando, o que se confirma pelas contagens no perfil dos complementos (vide amostragem compl1 e compl2 em ~11% dos casos de n_latlon). A rigor o IBGE registrou "endereços domicíliares", não apenas "endereços de rua". Neste relatório denominaremos o primeiro de domicílio (dom) e o segundo de endereço de fato (end) ou ponto.
- A escolha entre Geohashes de 9 ou 10 metros dependeria da precisão média dos pontos do IBGE. Como demonstra a nuvem de pontos, é bastante
- A contagem de n_ghs9 fez uso de Geohashes de 9 dígitos, garantindo a precisão da ordem de 5 metros, ou seja, superior ao erro de GPS da núvem de pontos. A contagem n_ghs9 resultou em 46%, bem longe dos 51% de n_latlon, gerando talvez duplicidade maior do que esperada. Como a precisão é variável (depende dos satélites GPS e do tempo de espera do agente), sugere-se usar ghs10 ou manter o ponto original e só depois do translado para a face de quadra (que aumenta a precisão) fazer a contagem de Geohashes ghs10.
nv_geo_coord | n_doms | perc |
---|---|---|
1 = Endereço - coordenada original do Censo 2022 | 630603 | 82.73% |
2 = Endereço - coordenada modificada (apartamentos em um mesmo número no logradouro). | 119942 | 15.74% |
3 = Endereço - coordenada estimada (endereços originalmente sem coordenadas ou coordenadas inválidas). | 8900 | 1.17% |
4 = Face de quadra. | 2753 | 0.36% |
5 = Localidade | 4 | 0.00% |
6 = Setor censitário | 37 | 0.00% |
-- por pontos únicos em ghs9 with t as (select count(distinct ghs9||nv_geo_coord) ntpt from vw02_ibge_cnefe2022) select nv_geo_coord, count(distinct ghs9) n_ghs9s, round(100.0*count(distinct ghs9)/t.ntpt,2)::text||'%' as perc from t,vw02_ibge_cnefe2022 group by 1,ntpt order by 1;
nv_geo_coord | n_ghs9s | perc |
---|---|---|
1 = Endereço - coordenada original do Censo 2022 | 343098 | 95.84% |
2 = Endereço - coordenada modificada (apartamentos em um mesmo número no logradouro). | 11224 | 3.14% |
3 = Endereço - coordenada estimada (endereços originalmente sem coordenadas ou coordenadas inválidas). | 2865 | 0.80% |
4 = Face de quadra. | 798 | 0.22% |
5 = Localidade | 3 | 0.00% |
6 = Setor censitário | 12 | 0.00% |
Conclusão: como queremos filtrar até o nível de pontos únicos, há garantia de 99,9% dos endereços em condição adequada (tipos 1 ou 2).
Filtragens
As filtragens seguem o seguinte passo a passo:
- Unicidade de endereço: DISTINCT cod_setor, cep, via_name, num_endereco
- Unicidade de posição: DISTINCT ghs
- Filtrando unicidades: primeiro de endereço, porém incluindo array de geohashes distintos. Se forem vizinhos não possuem mesmo prefixo conferir maior distancia entre eles.
CREATE FUNCTION hcodes_sameparent(g text[]) RETURNS boolean AS $f$ SELECT bool_and( CASE WHEN l1=l2 THEN substr(g1,1,l1-1)=substr(g2,1,l2-1) WHEN l1>l2 THEN g1 ~ ('^'||g2) -- WHEN l1=l2+1 ELSE g2 ~ ('^'||g1) -- WHEN l2=l1+1 ELSE false END ) FROM ( select g1, g2, length(g1) l1, length(g2) l2 from unnest(g) WITH ORDINALITY AS a(g1,i1) inner join unnest(g) WITH ORDINALITY AS b(g2,i2) on i1<i2 ) t1 $f$ LANGUAGE SQL; CREATE FUNCTION geoms_maxdist(g geometry[], use_spheroid boolean default false) RETURNS float AS $f$ SELECT MAX( ST_Distance(g1,g2,use_spheroid) ) FROM unnest(g) WITH ORDINALITY AS a(g1,i1) INNER JOIN unnest(g) WITH ORDINALITY AS b(g2,i2) ON i1<i2 $f$ LANGUAGE SQL; create table tmp_ibge_cnefe2022_uniq1 AS -- unicidade básica, ainda com repetição de pontos SELECT DISTINCT ghs, via_name, num_endereco FROM vw02_ibge_cnefe2022 ; -- 379228 de 762239 = select round(100.0*379228.0/762239); = 50% select avg(n) from (select ghs, count(*) n from ibge_cnefe2022_uniq1 group by 1) t where n=1 -- n>1 ; -- 325993 não-duplicados mais 2.16*24642 duplicados = 325993+2.16*24642 = 379220 ~ 379228.
Só na redução de pontos para 50% já é bem drástica, provavelmente inclui casos que diferenciam apenas no complemento. Desses, com duplicidade posicional apenas ~7,6% (24642 de 325993), sendo também razoável o seu descarte de tmp_ibge_cnefe2022_uniq1.
drop table if exists ibge_cnefe2022_uniq2; create table ibge_cnefe2022_uniq2 AS -- remove endereços duplicados em locais diferentes select v.cod_setor, v.num_quadra, v.num_face, v.cep, v.via_name, v.num_endereco, array_agg(v.ghs) ghss, array_agg(v.geom) geoms from( SELECT DISTINCT ON (ghs) ghs, via_name, num_endereco, count(*) OVER (PARTITION BY ghs) AS ghs_count FROM tmp_ibge_cnefe2022_uniq1 ) g -- 325993 INNER JOIN vw02_ibge_cnefe2022 v ON 1=g.ghs_count AND g.ghs=v.ghs group by 1,2,3,4,5,6 order by 1,2,3,4,5,6 ; -- 257387 select count(*) from (select cep, via_name, num_endereco, hcodes_sameparent(ghss) as is_same from ibge_cnefe2022_uniq2 where cardinality(ghss)>1 ) where is_same;-- 49597 select count(*) from (select cep, via_name, num_endereco, hcodes_sameparent(ghss) as is_same from ibge_cnefe2022_uniq2 where cardinality(ghss)>1 ) where not(is_same); -- 22523 -- conclusão: vale a pena manter o same, removendo o último dígito, fornecendo um booleano para usuário decidir se valido ou não. -- os casos de não same podem ser resgatados por geometria select count(*), avg(dist) from (select geoms_maxdist(geoms,true) dist from (select cep, via_name, num_endereco, hcodes_sameparent(ghss) as is_same, geoms from ibge_cnefe2022_uniq2 where cardinality(ghss)>1 ) where not(is_same)) where dist<=20; -- 12193 select count(*), avg(dist) from (select geoms_maxdist(geoms,true) dist from (select cep, via_name, num_endereco, hcodes_sameparent(ghss) as is_same, geoms from ibge_cnefe2022_uniq2 where cardinality(ghss)>1 ) where not(is_same)) where dist<=5; -- 1848 (não compensa) select count(*), avg(dist) from (select geoms_maxdist(geoms,true) dist from (select cep, via_name, num_endereco, hcodes_sameparent(ghss) as is_same, geoms from ibge_cnefe2022_uniq2 where cardinality(ghss)>1 ) t2 where is_same) t3 -- 49597 | 2.67 (ok distancia pequena e numero expressivo) select count(*), count(distinct via_name||num_endereco) from (select distinct cod_setor, via_name, num_endereco, cep from vw02_ibge_cnefe2022 ) t; -- 288685 | 277160
Tratamentos finais
drop table ibge_cnefe2022_uniq3; CREATE TABLE ibge_cnefe2022_uniq3 AS SELECT ghss[1] as ghs, cod_setor, num_quadra::int as num_quadra, num_face::int num_face, cep, via_name, num_endereco, false AS is_centroid FROM ibge_cnefe2022_uniq2 WHERE cardinality(ghss)=1 UNION ALL SELECT st_geohash(geoms_centroid(geoms),9) as ghs, cod_setor, num_quadra::int, num_face::int, cep, via_name, num_endereco, true AS is_centroid FROM ibge_cnefe2022_uniq2 WHERE cardinality(ghss)>1 AND (hcodes_sameparent(ghss) OR (geoms_maxdist(geoms,true))[2]<=20) ORDER BY 1 ; -- 249834 ---- copy ibge_cnefe2022_uniq3 to '/tmp/BR-RS-POA2024_CNEFE-ptsEnderecoUnico.csv' CSV HEADER; copy (select gid, cd_setor, cd_quadra::int as cd_quadra, cd_face::int as cd_face, via_name, tot_res, geom FROM vw01_log) TO '/tmp/BR-RS-POA-faces.csv' CSV HEADER; -- COPY 56645 --- CONTAGENS DE JOIN With f AS( SELECT gid, cd_setor, cd_quadra::int as cd_quadra, cd_face::int as cd_face, via_name, tot_res, st_geohash(geom,7) as ghs7 FROM vw01_log ) SELECT count(*) FROM ibge_cnefe2022_uniq3 u INNER JOIN f ON substring(u.cod_setor,1,15)!=f.cd_setor AND substring(u.ghs,1,7)=f.ghs7 AND f.cd_quadra=u.num_quadra AND f.cd_face=u.num_face AND f.via_name=u.via_name ; -- 5893 -- testar se são consistentes ON substring(u.ghs,1,7)=f.ghs7 AND f.cd_quadra=u.num_quadra AND f.cd_face=u.num_face AND f.via_name=u.via_name ------- final só confiaveis: drop table ibge_cnefe2022_uniq_onface; create table ibge_cnefe2022_uniq_onface AS WITH f AS ( SELECT gid, cd_setor, cd_quadra::int as cd_quadra, cd_face::int as cd_face, via_name, tot_res, st_geohash(geom,7) as ghs7, geom FROM vw01_log ) SELECT u.ghs, u.cep, u.via_name, u.num_endereco, u.is_centroid, substring(u.ghs,1,7)=f.ghs7 as is_nearface, ST_ClosestPoint(f.geom, ST_PointFromGeoHash(u.ghs)) as geom FROM ibge_cnefe2022_uniq3 u INNER JOIN f ON substring(u.cod_setor,1,15)=f.cd_setor AND f.cd_quadra=u.num_quadra AND f.cd_face=u.num_face AND f.via_name=u.via_name order by 1 ; -- 198797