calcular el porcentaje de área de intersección en la cláusula where

15

Tengo una tabla de polígonos (grupos de bloques censales) en postgres. Quiero etiquetar cada grupo de bloques con la ciudad (otra tabla de polígonos) en la que reside principalmente. es posible? Estoy pensando que esencialmente necesitaría crear algo como:

select b.*,t.name  
from blockgroups b, towns t  
where (st_area(st_intersection(b.wkb_geometry, t.wkb_geometry))/st_area(b.wkb_geometry)) > .5  

pero esta consulta lleva una eternidad (tengo alrededor de 5,000 grupos de bloques y 375 ciudades ...). ¿Alguna sugerencia sobre cómo hacer que esta consulta funcione si es incorrecta o más rápida si es correcta?

eirvin
fuente
¿Parece que quieres etiquetar los grupos de bloques en función de la superposición máxima? Si es así, mira esta respuesta . Si sus 'ciudades' también son geografías censales (MCD o lugares, por ejemplo), probablemente no haya necesidad de calcular el porcentaje de superposición.
dbaston

Respuestas:

23

La forma en que lo hace funcionará, pero tomará demasiado tiempo, ya que postgis está tratando de crear la geometría de la intersección de cada combinación de "grupo de bloques vs ciudad", incluso cuando ni siquiera se tocan.

Agregue otra verificación de condición a su cláusula WHERE para verificar si las dos geometrías interceptan y póngala antes de la existente:

select b.*,t.name
from blockgroups b, towns t
where st_intersects(b.wkb_geometry, t.wkb_geometry) and    
    (st_area(st_intersection(b.wkb_geometry, t.wkb_geometry))/st_area(b.wkb_geometry)) > .5

En SQL, si tiene una lista de condiciones en la cláusula WHERE, se prueban por el orden en que se escriben. Si se devuelve un FALSO en una de las primeras operaciones, la consulta simplemente omitirá la comprobación de otras condiciones, ya que el resultado será siempre FALSO.

Además, asegúrese de tener índices espaciales en blockgroups.wkb_geometry y towns.wkb_geometry.

Alexandre Neto
fuente
1
Agregar ST_Intersectses la forma correcta de hacerlo aquí, pero el planificador puede o no ejecutar las condiciones en el orden en que están escritas. Vea los documentos de Postgres para más detalles sobre esto. ST_Intersectsy ST_Intersectiontengo el mismo costo en mi instalación (100), así que para ser honesto, no estoy seguro de lo que está haciendo el planificador, pero siempre parece hacer lo correcto aquí.
dbaston
Ahh ... asumí que las condiciones se comprobarían como en otros idiomas. Pero supongo que le da al planificador otra opción.
Alexandre Neto
10

Además de la muy útil respuesta de Alexandre, si algunas de sus unidades censales pueden abarcar tres de sus ciudades (y, por lo tanto, no puede garantizar más del 50% de caídas en cualquier ciudad), puede hacer esto:

select distinct on (b.id)
b.*,t.name,
(st_area(st_intersection(b.wkb_geometry, t.wkb_geometry))/st_area(b.wkb_geometry)) as proportion
from blockgroups b, towns t
where st_intersects(b.wkb_geometry, t.wkb_geometry) 
order by b.id, proportion desc;

Esto básicamente protege contra la siguiente situación, en la que las áreas en azul desaparecerían: ingrese la descripción de la imagen aquí

RobinL
fuente
1
Me encanta cuando el primer problema que encuentro con una respuesta SO se resuelve con la siguiente respuesta. Saludos, @RobinL!
wfgeo