2 억 포인트의 Point in Polygon 분석을위한 가장 빠른 솔루션을 찾고 있습니다.


35

다음 형식의 2 억 개의 관측치가 포함 된 CSV가 있습니다.

id,x1,y1,x2,y2,day,color
1,"-105.4652334","39.2586939","-105.4321296","39.2236632","Monday","Black"
2,"-105.3224523","39.1323299","-105.4439944","39.3352235","Tuesday","Green"
3,"-104.4233452","39.0234355","-105.4643990","39.1223435","Wednesday","Blue"

, 나는 그것이 내에있는 미국 인구 요로 또는 인구 조사 블록을 할당 할 좌표 (X1 / Y1 및 X2 / Y2)의 각 세트의 (I 여기에 인구 조사 기관 TIGER의 Shape 파일을 다운로드 한 ftp://ftp2.census.gov/를 geo / tiger / TIGER2011 / TRACT / tl_2011_08_tract.zip ). 따라서 각 관측치에 대해 다각형 내 작업을 두 번 수행해야합니다. 일치하는 내용이 매우 정확해야합니다.

소프트웨어 학습 시간을 포함하여 가장 빠른 방법은 무엇입니까? 48GB의 메모리가있는 컴퓨터에 액세스 할 수 있습니다-관련 제약이있을 수 있습니다.

여러 스레드에서 PostGIS 또는 Spatialite를 사용하는 것이 좋습니다 (Spatialite는 사용하기 쉬워 보이지만 PostGIS만큼 효율적입니까?). 이것이 최선의 선택이라면, 공간 인덱스 (RTree?)를 채워야합니까? 그렇다면 어떻게해야합니까 (예 : 인구 조사 구역 셰이프 파일 사용)? 예제 코드 (또는 예제 코드에 대한 포인터)가 포함 된 권장 사항에 대해 매우 감사드립니다.

나의 첫 번째 시도 (이 사이트를 찾기 전에)는 ArcGIS를 사용하여 US Census Block에서 데이터의 하위 샘플 (100,000 포인트)의 공간 조인 (x1 / y1 만)을 수행하는 것으로 구성되었습니다. 프로세스를 종료하기까지 5 시간이 걸렸습니다. 40 시간 미만의 컴퓨팅 시간 내에 전체 데이터 세트에 구현할 수있는 솔루션을 원합니다.

이전에 질문을 한 것에 대한 사과-답변을 읽었으며 권장 사항을 구현하는 방법이 궁금합니다. 저는 SQL, Python, C를 사용한 적이 없으며 ArcGIS를 한 번만 사용한 적이 있습니다. 저는 초보자입니다.


3
40 시간은 초당 거의 2800 포인트 폴리 인 작업과 같습니다. 내 마음 속에는 들리지 않습니다. 어떤 소프트웨어 (ArcGIS, PostGIS, Spatialite 등)가 가장 빠르지는 모르겠지만 공간 인덱스는 의심의 여지가 없습니다.
Uffe Kousgaard

1
다각형이 복잡하지 않으면 문제가되지 않습니다. PostGIS에서 인덱스의 게인은 다각형의 크기에 따라 다릅니다. 다각형이 작을수록 (경계가 작을수록) 색인이 더 도움이됩니다. 아마 가능합니다.
Nicklas Avén

다각형 당 ~ 600 개의 점이있는 1249 개의 다각형
Uffe Kousgaard

3
@ Uffe Kousgaard, 그렇습니다 절대적으로 가능합니다. 당신은 내가 그것을 시도하게했다. 아래 답변입니다.
Nicklas Avén

도전에 도전 해 주셔서 감사합니다! 일부 벤치 테스트에서 SpatialLite는 실제로 PostGIS보다 빠르게 수행되지만 RTree를 설정하는 방법에주의해야합니다. 또한 종종 '내부'에서 실행할 때 ArcGIS가 느리지 만 '독립형'ArcPy 모듈 '외부'로 실행할 때 더 빠릅니다.
MappaGnosis

답변:


26

ST_DWithin 내 테스트에서 ST_Intersects보다 빠릅니다. 준비된 지오메트리 알고리즘이 이와 같은 경우에 적용되기 때문에 특히 놀랍습니다. 나는 이것이 내가 여기에 보여준 것보다 훨씬 빠를 가능성이 있다고 생각합니다.


나는 더 많은 테스트를했고 두 가지가 속도를 거의 두 배로 늘 렸습니다. 첫째, 나는 새로운 컴퓨터에서 시도했지만 SATA3 ssd -disks를 제외하고는 여전히 일반적인 랩톱입니다.

그런 다음 이전 노트북에서 62 초 대신 18 초가 걸렸습니다. 다음으로 포인트 테이블의 인덱스가 필요하지 않다고 썼을 때 완전히 잘못되었다는 것을 알았습니다. 이 인덱스가 있으면 ST_Intersects가 예상대로 작동하고 상황이 매우 빨라졌습니다. 포인트 테이블의 포인트 수를 백만 포인트로 늘리고 쿼리 :

CREATE TABLE points_ct AS
SELECT imported_ct.gid as ct_gid, t.gid as point_id 
FROM imported_ct , t WHERE ST_Intersects(imported_ct.geom , t.geom);

72 초 안에 실행됩니다. 1249 개의 다각형이 있으므로 1249000000 개의 테스트가 72 초 안에 수행됩니다. 초당 약 17000000 개의 테스트가 수행됩니다. 또는 초당 모든 다각형에 대해 거의 14000 포인트를 테스트합니다.

이 테스트에서 400000000 포인트 테스트는로드를 여러 코어에 분배하는 데 아무런 어려움없이 약 8 시간이 소요됩니다. PostGIS는 나에게 감동을 멈추지 않습니다 :-)


먼저 결과를 시각화하기 위해 결과 지오메트리를 결과 테이블에 추가하고이를 QGIS에서 열고 import_ct 필드에서 고유 한 값으로 스타일을 지정할 수 있습니다.

둘째, 다음과 같이 오른쪽 (또는 왼쪽) 조인을 사용하여 다각형 바깥으로 떨어지는 점을 얻을 수도 있습니다.

CREATE TABLE points_ct AS
SELECT imported_ct.gid as ct_gid, t.gid as point_id 
FROM imported_ct right join t ON ST_Intersects(imported_ct.the_geom , t.geom);

PostGIS가 가능한지 확인하기 위해 몇 가지 테스트를 수행했습니다.

먼저 이해가 안되는 것. 행당 두 점이 있습니다. 두 점이 항상 같은 다각형에 있습니까? 그런 다음 포인트 중 하나에서 계산을 수행하면 충분합니다. 두 개의 다른 다각형에있을 수 있으면 한 점 행을 두 개의 다각형에 연결하는 방법이 필요합니다.

테스트에서 가능한 것처럼 보이지만 둘 이상의 CPU 코어에 부하를 분산시키기 위해서는 창의적인 솔루션이 필요할 수 있습니다.

듀얼 코어 센트리노 CPU (약 2.2GHz라고 생각합니다), 2GB RAM이 장착 된 4 세짜리 랩톱에서 테스트했습니다. BG RAM이 48 개인 경우 CPU 성능이 훨씬 더 뛰어납니다.

내가 한 것은 다음과 같이 100000 점으로 임의의 점 테이블을 만드는 것이 었습니다.

CREATE TABLE t AS
WITH r AS
(SELECT ST_Extent(the_geom)::geometry ext FROM imported_ct)
SELECT ST_Point(x,y) AS geom FROM 
(SELECT GENERATE_SERIES(1,100000)) s,
(SELECT ST_Xmin(ext)+(random()*(ST_Xmax(ext)-ST_Xmin(ext))) x, ST_Ymin(ext)+(random()*(ST_Ymax(ext)-ST_Ymin(ext))) y FROM r
) f;

그런 다음 다음과 같은 gid를 추가하십시오.

ALTER TABLE t ADD COLUMN GID SERIAL;

그런 다음 :

CREATE TABLE points_ct AS
SELECT imported_ct.gid as ct_gid, t.gid as point_id FROM imported_ct , t WHERE ST_Dwithin(imported_ct.the_geom , t.geom,0);

약 62 초가 소요됩니다 (ArcGIS 결과와 동일한 양의 포인트 비교). 결과는 내 테이블 t의 포인트를 인구 조사가있는 테이블의 gid와 연결하는 테이블입니다.

이 속도로 약 34 시간 내에 200 밀 포인트를 수행합니다. 따라서 포인트 중 하나를 확인하는 것으로 충분하면 이전 랩톱이 하나의 코어로 수행 할 수 있습니다.

그러나 두 지점을 모두 확인해야 할 경우 더 어려울 수 있습니다.

따라서 db에 대해 여러 세션을 시작하고 다른 쿼리를 실행하여 둘 이상의 코어에 수동으로로드를 분배 할 수 있습니다.

50000 점과 두 개의 CPU 코어가있는 예에서 나는 시도했다.

CREATE TABLE t1 as
SELECT imported_ct.gid as ct_gid, t.gid as point_id FROM imported_ct , t WHERE t.gid >50000 and  ST_Dwithin(imported_ct.the_geom , t.geom,0);

하나의 db-session에서 실행과 동시에

CREATE TABLE t2 as
SELECT imported_ct.gid as ct_gid, t.gid as point_id FROM imported_ct , t WHERE t.gid <=50000 and  ST_Dwithin(imported_ct.the_geom , t.geom,0);

다른 DB 세션에서.

약 36 초가 걸렸으므로 디스크 쓰기에 따라 첫 번째 예보다 약간 느립니다. 그러나 바이트 코어가 동시에 작동하기 때문에 36 초 이상 걸리지 않았습니다.

테이블 t1과 t2를 통합하려면 다음을 시도하십시오.

CREATE TABLE t3 AS 
SELECT * FROM t1
UNION ALL
SELECT * FROM t2;

약 0.5 초를 사용합니다.

따라서 최신 하드웨어를 사용하고 많은 코어에 부하를 분산 시키면 실제 상황이 테스트 케이스보다 느리더라도 이것이 가능합니다.

예제는 Linux (Ubuntu)에서 나온 것입니다. Windows를 사용하는 것도 또 다른 이야기가 될 것입니다. 그러나 다른 모든 일상적인 응용 프로그램을 실행 중이므로 랩톱이 이전보다 상당히 많이로드되었습니다. 따라서 pgadmin 이외의 다른 것을 열지 않고도 Windows 사례를 잘 시뮬레이션 할 수 있습니다.


1
작성하기 쉽기 때문에 .tl_2011_08_trac의 이름을 import_ct로 바꿨습니다. 따라서 내 쿼리에서 import_ct를 .tl_2011_08_trac로 변경하면 정상적으로 진행됩니다.
Nicklas Avén

2
@meer BTW, template_postgis_20을 향후 데이터베이스 용 템플릿 이외의 다른 것으로 사용하는 것은 권장되지 않습니다. PostGIS 2.0이있는 것 같습니다. PostgreSQL 9.1도있는 경우 새 db를 생성하고 "CREATE EXTENSION POSTGIS;"를 실행하면됩니다.
Nicklas Avén

1
그렇습니다. 몇 분 전에 고쳐 놓은 또 다른 오타였습니다. 미안합니다. 대신 ST_Intersects 버전을 사용해보십시오. 상당히 빠릅니다.
Nicklas Avén

1
@meer 모든 점에 영향을 미치지 않는 이유는 임의의 점이 직교에 배치되어 있기 때문에지도가 정확히 직교가 아니기 때문입니다. 게시물을 수정하여 결과를 보는 방법을 보여 드리겠습니다.
Nicklas Avén

1
@ Uffe Kousgaard, 예, 당신이 그렇게 넣을 수 있다고 생각합니다. 한 번에 하나의 다각형이 필요하며 가장자리의 나무를 만들어 다각형을 준비합니다. 그런 다음 준비된 다각형과 비교하여 모든 점 (인덱스가 겹치는 박스로 정렬 됨)을 확인합니다.
Nicklas Avén

4

아마도 가장 쉬운 방법은 PostGIS입니다. 인터넷에서 csv / txt 포인트 데이터를 PostGIS로 가져 오는 방법에 대한 튜토리얼이 있습니다. 링크 1

PostGIS에서 다각형 내 검색의 성능에 대해 잘 모르겠습니다. ArcGIS보다 빠릅니다. PostGIS가 사용하는 GIST 공간 인덱스는 매우 빠릅니다. Link2 Link3

MongoDB 지리 공간 인덱스를 테스트 할 수도 있습니다 . 그러나 시작하는 데 시간이 조금 더 걸립니다. MongoDB가 정말 빠를 수 있다고 생각합니다. 다각형 검색으로 테스트하지 않았으므로 확실하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.