简体   繁体   中英

PostGIS - Count Points in Polygons (and average their features within the boundaries)

I've a table with some points representing buildings :

CREATE TABLE buildings(
  pk serial NOT NULL,
  geom geometry(Point,4326),
  height double precision,
  area double precision,
  perimeter double precision
)

And another table with polylines (most of them closed):

CREATE TABLE regions
(
  pk serial NOT NULL,
  geom geometry(Polygon,4326)
)

I would like to:

  1. count the numbers of points inside each regions (buildings_n)
  2. find the average value of one the features(eg. area) within the regions boundary (area_avg)

Adding the two new columns:

ALTER TABLE regions ADD COLUMN buildings_n integer;
ALTER TABLE regions ADD COLUMN area_avg double precision;

How can I do these two queries?

I've tried this one for the point 1, but it fails:

INSERT INTO  regions (buildings_n)
SELECT  count(b.geom) 
FROM  regions a, buildings b
WHERE st_contains(a.geom,b.geom); 

thank you,

Stefano

Region geometry

The first problem you have is that ST_Contains with 'polylines' or linestrings only finds the points that are exactly on the linestring's geometry. If you want points within a region represented by a linestring it won't work, especially if these are not closed. See the examples of valid ST_Contains relations here: http://www.postgis.org/docs/ST_Contains.html

For the spatial relation to work you have to transform the region's geometry to polygons, either beforehand or on the fly in the query. For example:

ST_Contains(ST_MakePolygon(a.geom),b.geom)

See this reference for more info: http://www.postgis.org/docs/ST_MakePolygon.html

Calculate aggregate values

The second problem is that to use the aggregate functions count or average on subsets of the buildings table (and not the entire table) you need to associate the region id with each building...

SELECT a.pk region_pk, b.pk building_pk, b.area
FROM regions a, buildings b
WHERE ST_Contains(ST_MakePolygon(a.geom),b.geom)

.. and then group your building data by the region they belong to:

SELECT region_pk, count(), avg(area) average
FROM joined_regions_and_buildings
GROUP BY region_pk;

Update new columns

The third problem is that you are using INSERT to add values to the newly created columns. INSERT is for adding new records to a table, UPDATE is used for changing values of existing records in a table.

Solution

So, all of the points above combined result in the following query:

WITH joined_regions_and_buildings AS (
    SELECT a.pk region_pk, b.pk building_pk, b.area
    FROM regions a, buildings b
    WHERE ST_Contains(ST_MakePolygon(a.geom),b.geom)
)
UPDATE regions a
SET buildings_n = b.count, area_avg = b.average
FROM (
    SELECT region_pk, count(), avg(area) average
    FROM joined_regions_and_buildings
    GROUP BY region_pk
    ) b
WHERE a.pk = b.region_pk;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM