简体   繁体   English

使用 PostGIS 从点数据生成热量/密度图

[英]Generating heat/density map with PostGIS from point data

I have a huge table (gps_points) with a geometry column storing 2D-points.我有一个巨大的表(gps_points),其中包含一个存储二维点的几何列。 What I'm trying to accomplish is to run a query that output something like我想要完成的是运行一个输出类似的查询

 id | freq
-------------
  1 | 365
  2 | 1092
  3 | 97
...

where "id" is a unique identifier of a small rectangle inside my total bounding box and "freq" is the number of points that fall inside that particular rectangle.其中“id”是我的总边界框内一个小矩形的唯一标识符,“freq”是落在该特定矩形内的点数。

So I have defined a PostGIS table as:因此,我将 PostGIS 表定义为:

create table sub_rects (
id int,
geom geometry)

I then run a script externally, where I generate 1000x1000 such rectangles and create polygons of them, so I get a million lines like this:然后我在外部运行一个脚本,在那里我生成 1000x1000 这样的矩形并创建它们的多边形,所以我得到了一百万行这样的:

insert into sub_rects values(1,ST_GeomFromText('POLYGON((1.1 1.2, 1.1 1.4, 1.5 1.4, 1.5 1.2, 1.1 1.2))'));

except of course every polygon gets itself a new set of co-ordinates to match its actual place in the 1000x1000 grid over the bounding box co-ordinates of my gps data, and the ID gets updated for each tuple.当然,除了每个多边形都会获得一组新的坐标,以匹配它在 1000x1000 网格中的实际位置,超过我的 gps 数据的边界框坐标,并且每个元组的 ID 都会更新。

Then I generate a spatial index and a primary key index on this table.然后我在这个表上生成一个空间索引和一个主键索引。

Finally I can run this table and my original data table (gps_points) with最后我可以运行这个表和我的原始数据表(gps_points)

select id, count(*) from sub_rects r join gps_points g on r.geom && g.geom group by id;

which gives me my sought output.这给了我我想要的输出。 The problem is that it takes forever to load all the little polygons and that every time I want to generate a map with a different number of rectangles or running over a data set with different underlying co-ordinates, I have to drop sub_rects and generate and load it anew.问题是加载所有小多边形需要很长时间,并且每次我想生成具有不同数量矩形的地图或运行具有不同基础坐标的数据集时,我必须删除 sub_rects 并生成和重新加载它。

Is there a better way of doing this?有没有更好的方法来做到这一点? I don't need graphic output.我不需要图形输出。 I just need to generate the data.我只需要生成数据。 Not having to generate the support table (sub_rects) externally would be very nice, and I suspect there are way less computationally expensive methods of accomplishing the same thing.不必在外部生成支持表(sub_rects)会非常好,而且我怀疑有一些计算成本更低的方法可以完成同样的事情。 I would much prefer not to have to install any additional software.我宁愿不必安装任何额外的软件。

ETA: As per request in comments, here is the query plan (on my home machine, so smaller data sets and other table names, but the same plan): ETA:根据评论中的要求,这是查询计划(在我的家用机器上,因此数据集和其他表名较小,但计划相同):

gisdb=# explain analyse select g.id id, count(*) from gridrect g join broadcast b on g.geom && b.wkb_geometry group by g.id;

    QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 GroupAggregate  (cost=0.57..177993.58 rows=10101 width=12) (actual time=14.740..3528.600 rows=1962 loops=1)
   Group Key: g.id
   ->  Nested Loop  (cost=0.57..144786.36 rows=6621242 width=4) (actual time=13.948..3050.741 rows=1366376 loops=1)
         ->  Index Scan using gridrect_id_idx on gridrect g  (cost=0.29..485.30 rows=10201 width=124) (actual time=0.079..6.582 rows=10201 loops=1)
         ->  Index Scan using broadcast_wkb_geometry_geom_idx on broadcast b  (cost=0.29..12.78 rows=137 width=32) (actual time=0.011..0.217 rows=134 loops=10201)
               Index Cond: (g.geom && wkb_geometry)
 Planning time: 0.591 ms
 Execution time: 3529.320 ms
(8 rows)

ETA 2:预计到达时间 2:

As per suggestions in the answers I modified the code suggested there to this:根据答案中的建议,我将那里建议的代码修改为:

(SELECT row_number() OVER (ORDER BY geom) id, geom
 FROM (SELECT st_geomfromtext(
                  concat('Polygon((', x || ' ' || y, ',', x + xstep || ' ' || y, ',', x + xstep || ' ' || y + ystep,
                         ',', x || ' ' || y + ystep, ',', x || ' ' || y, '))')) geom
       FROM (SELECT x, y
             FROM (SELECT generate_series(xmin, xmin + xdelta, xstep) x) x,
                  (SELECT generate_series(ymin, ymin + ydelta, ystep) y) y) foo) bar);

where xmin, ymin, xdelta, ydelta, xstep and ystep are all calculated by an external script, but might just as well be calculated as a part of a Postgres function if you wrapped the above in a function call.其中 xmin、ymin、xdelta、ydelta、xstep 和 ystep 都由外部脚本计算,但如果您将上述内容包装在函数调用中,也可以作为 Postgres 函数的一部分进行计算。 Generating a temporary table from this and running the queries against that is two orders of magnitude faster than what I was doing initially.从中生成一个临时表并对其运行查询比我最初做的要快两个数量级。

Two things.两件事情。 First create table on sql level (from pg_admin for exmaple).首先在 sql 级别创建表(例如来自 pg_admin)。

create table polygons as
select st_geomfromtext(concat('Polygon((',x||' '||y,',',x||' 
'||y+0.2,',',x+0.4||' '||y+0.2,',',x+0.4||' '||y,',',x||' '||y,'))')) geom
  FROM (select generate_series(0,199.9,0.2) x) x,
       (select generate_series(0,199.9,0.4) y) y

Create index创建索引

create index on polygons using gist(geom);使用 gist(geom) 在多边形上创建索引;

Then use your query or this one.然后使用您的查询或这个。 Check which one will be faster in your case检查在您的情况下哪一个会更快

select id, count(*) 
  from sub_rects r 
  join gps_points g on st_dwithin(r.geom, p.geom, 0)
group by id;

Here's an example of generating a grid from a bounding box:这是从边界框生成网格的示例:

https://gis.stackexchange.com/questions/16374/how-to-create-a-regular-polygon-grid-in-postgis https://gis.stackexchange.com/questions/16374/how-to-create-a-regular-polygon-grid-in-postgis

To generate the density data, try creating a temp table with all the data first and then get the count.要生成密度数据,请尝试先创建一个包含所有数据的临时表,然后获取计数。 In my experience the below was somewhat faster than combing all into a single query:根据我的经验,以下内容比将所有查询合并为一个查询要快一些:

create temp table rect_points as 
select r.id as rect_id, p.id as point_id 
from sub_rects r, gps_points p
where p.geom && r.geom;

create index idx on rect_points (rect_id);

select rect_id, count(*) from rect_points group by rect_id; 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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