# create the areacommand table with name and geometry field # the area command filed has a lenth of 20 in the ArcServer service cursor.execute('create table areacommand (id SERIAL PRIMARY KEY, name VARCHAR(20),' 'geom GEOMETRY)')
# create the beats table cursor.execute('CREATE TABLE beats (id SERIAL PRIMARY KEY, beat VARCHAR(6),' 'agency VARCHAR(3), areacomm VARCHAR(15), geom GEOMETRY)')
# create the incidents table cursor.execute('CREATE TABLE incidents (id SERIAL PRIMARY KEY, address VARCHAR(72), ' 'crimetype VARCHAR(255), date DATE, geom GEOMETRY)')
# grab the area commands and insert them into table url='http://coagisweb.cabq.gov/arcgis/rest/services/public/adminboundaries/MapServer/8/query' params={"where":"1=1","outFields":"*","outSR":"4326","f":"json"}
# query the url passing parameters r=requests.get(url,params=params, proxies=proxies) data=r.json()
# insert the data for acmd in data['features']: polys=[]
# loop through the rings # A polygon contains an array of rings and a spatialReference. # Each ring is represented as an array of points. for ring in acmd['geometry']['rings']: polys.append(Polygon(ring)) p=MultiPolygon(polys) name=acmd['attributes']['Area_Command']
# uses Shapely to convert the coordinates to WKT (p.wkt). cursor.execute("INSERT INTO areacommand (name, geom) VALUES ('{}',ST_GeomFromText('{}'))".format(name, p.wkt))
connection.commit()
上面SQL查询的关键是INSERT INTO table (field, field) VALUES (value,value)命令,其中潜逃了ST_GeometryFromText()命令。ST_GeometryFromText和ST_GeomFromText一样,根据WKT描述的对象返回一个具体的geometry对象,WKT可以是POLYGON、MULTIPOLYGON、LINESTRING等。
url='http://coagisweb.cabq.gov/arcgis/rest/services/public/APD_Incidents/MapServer/0/query' params={"where":"1=1","outFields":"*","outSR":"4326","f":"json"} r=requests.get(url,params=params, proxies=proxies) data=r.json() for a in data["features"]: address=a["attributes"]["BlockAddress"] crimetype=a["attributes"]["IncidentType"] if a['attributes']['date'] isNone: pass else: date = datetime.datetime.fromtimestamp(a['attributes']['date'] /1e3).date()
import psycopg2 from shapely.geometry import Point, Polygon, MultiPolygon from shapely.wkb import loads from shapely.wkt import dumps, loads import datetime import json import ipyleaflet as ipl
1 2 3 4 5
connection = psycopg2.connect(database='pythonspatial', user='postgres', password='postgres') cursor = connection.cursor() cursor.execute('SELECT name, ST_AsGeoJSON(geom) from areacommand') c = cursor.fetchall() c[0][0]
center = [35.106196, -106.629515] # the zoom level—the higher the number, the closer the zoom. zoom = 9 map = ipl.Map(center=center, zoom=zoom)
for x in c: layer = json.loads(x[1]) layer_geojson = ipl.GeoJSON(data=layer) map.add_layer(layer_geojson) map
ipyleaflet控件在转换为markdown文件时无法显示,所以我用folium来作图。
1 2 3 4 5 6
import folium map = folium.Map(center, zoom_start=9,control_scale=True) for x in c: layer = json.loads(x[1]) folium.GeoJson(layer).add_to(map) map
1 2 3 4 5 6 7
# map the beats in a similar way cursor.execute('SELECT beat, ST_AsGeoJSON(geom) from beats') c = cursor.fetchall() for x in c: layer = json.loads(x[1]) layer_geojson = ipl.GeoJSON(data=layer) map.add_layer(layer_geojson)
center = [35.106196, -106.629515] # the zoom level—the higher the number, the closer the zoom. zoom = 9 map = folium.Map(center, zoom_start=zoom) date = datetime.datetime.strptime('20181031', '%Y%m%d').date() print(date) cursor.execute("SELECT address, crimetype, date, ST_AsGeoJSON(geom) from incidents where date = '{}'".format(str(date))) incidents_date = cursor.fetchall()
for x in incidents_date: layer = json.loads(x[3]) folium.Marker([layer['coordinates'][1], layer['coordinates'][0]]).add_to(map) map.save('crimes_by_date.html') map
center = [35.106196, -106.629515] # the zoom level—the higher the number, the closer the zoom. zoom = 10 map = folium.Map(center, zoom_start=zoom)
cursor.execute("SELECT ST_AsGeoJSON(i.geom) FROM incidents i JOIN areacommand acmd ON ST_Intersects(acmd.geom, i.geom)" " WHERE acmd.name like'FOOTHILLS' and date >= NOW() - interval '12 day';") crime = cursor.fetchall() for x in crime: layer = json.loads(x[0]) folium.Marker([layer['coordinates'][1], layer['coordinates'][0]]).add_to(map)
cursor.execute("SELECT name, ST_AsGeoJSON(geom) from areacommand WHERE name like 'FOOTHILLS'") foothills= cursor.fetchall()
上面查询了在Foothills区域最近10天的事件。在具体的操作上,需要使用JOIN命令实现多个表的合并查询,考虑到空间合并查询的特殊性,PostGIS提供了ST_Intersects, ST_Contains, and ST_DWithin等多种合并方式,其中我们用的是ST_Intersects。关于命令的使用方法参见:
center = [35.106196, -106.629515] # the zoom level—the higher the number, the closer the zoom. zoom = 11 map = folium.Map(center, zoom_start=zoom)
cursor.execute("SELECT ST_AsGeoJSON(i.geom) FROM incidents i JOIN beats b ON " "ST_Intersects(b.geom, i.geom) WHERE b.beat in ('336','523','117','226','638','636') " "and date >= NOW() - interval '20 day';") crime = cursor.fetchall() for x in crime: layer = json.loads(x[0]) folium.Marker([layer['coordinates'][1], layer['coordinates'][0]]).add_to(map)
cursor.execute("SELECT beat, ST_AsGeoJSON(geom) from beats WHERE beat in ('336','523','117','226','638','636')") beats = cursor.fetchall() for b in beats: layer = json.loads(b[1]) folium.GeoJson(layer).add_to(map) map.save('crimes_by_beats.html') map
center = [35.062485, -106.578677] # the zoom level—the higher the number, the closer the zoom. zoom = 12 map = folium.Map(center, zoom_start=zoom) p = Point([-106.578677,35.062485]) folium.Marker([35.062485, -106.578677]).add_to(map)
cursor.execute("SELECT ST_AsText(ST_Buffer(ST_GeomFromText('{}')" "::geography, 1500));".format(p.wkt)) bufferwkt = cursor.fetchall() b = loads(bufferwkt[0][0])
cursor.execute("SELECT ST_AsGeoJSON(incidents.geom) FROM incidents where " "ST_Intersects(ST_GeomFromText('{}'), incidents.geom) and date >= " "Now() - interval '12 day';".format(b.wkt)) crime = cursor.fetchall() for x in crime: layer = json.loads(x[0]) folium.Marker([layer['coordinates'][1], layer['coordinates'][0]]).add_to(map) map.save('crimes_in_buffer.html') map
center = [35.062485, -106.578677] # the zoom level—the higher the number, the closer the zoom. zoom = 12 map = folium.Map(center, zoom_start=zoom)
p = Point([-106.578677,35.062485]) cursor.execute("SELECT ST_AsGeoJSON(incidents.geom),ST_Distance(" "incidents.geom::geography,ST_GeometryFromText('{}')::geography)" "from incidents ORDER BY incidents.geom<->ST_GeometryFromText('{}') " "LIMIT 5".format(p.wkt,p.wkt))
c = cursor.fetchall() for x in c: layer=json.loads(x[0]) folium.Marker([layer['coordinates'][1], layer['coordinates'][0]]).add_to(map) print(layer) map.save('crime_knn.html') map
from ipywidgets import interact, interactive, fixed, interact_manual, DatePicker
@widgets.interact(x=DatePicker()) defmap_by_date(x): if x: for l inmap.layers[1:]: map.remove_layer(l) cursor.execute("SELECT ST_AsGeoJSON(geom) from incidents where " "date = '{}'".format(str(x))) c = cursor.fetchall() for x in c: layer = json.loads(x[0]) layer_geojson = ipl.GeoJSON(data=layer) map.add_layer(layer_geojson) returnlen(c) else: pass
center = [35.106196, -106.629515] # the zoom level—the higher the number, the closer the zoom. zoom = 10 map = ipl.Map(center=center, zoom=zoom) map
@widgets.interact(x='None') defmap_by_area(x): if x: for l inmap.layers[1:]: map.remove_layer(l) cursor.execute("SELECT ST_AsGeoJSON(i.geom) FROM incidents i JOIN " "areacommand acmd ON ST_Intersects(acmd.geom, i.geom)" " WHERE acmd.name like '{}' and date >= NOW() - interval " "'10 day';".format(x)) c = cursor.fetchall()
for x in c: layer = json.loads(x[0]) layer_geojson = ipl.GeoJSON(data=layer) map.add_layer(layer_geojson) return c else: pass center = [35.106196, -106.629515] # the zoom level—the higher the number, the closer the zoom. zoom = 10 map = ipl.Map(center=center, zoom=zoom) map
import pandas as pd d = datetime.datetime.strptime('20180101', '%Y%m%d').date() cursor.execute("SELECT date, count(date) from incidents where date >'{}'" "group by date".format(str(d))) df = pd.DataFrame(cursor.fetchall(), columns=['date', 'counts'])
query=('CREATE FUNCTION newcrime()\n' 'RETURNS trigger\n' 'AS $newcrime$\n' 'BEGIN\n' 'IF NEW.crimetype IS NULL THEN\n' 'RAISE EXCEPTION' +" '% Must Include Crime Type', NEW.address;"+'\n' 'END IF;\n' 'RETURN NEW;\n' 'END;\n' '$newcrime$\n' 'LANGUAGE \'plpgsql\';' ) print(query) cursor.execute(query)
CREATE FUNCTION newcrime()
RETURNS trigger
AS $newcrime$
BEGIN
IF NEW.crimetype IS NULL THEN
RAISE EXCEPTION '% Must Include Crime Type', NEW.address;
END IF;
RETURN NEW;
END;
$newcrime$
LANGUAGE 'plpgsql';
---------------------------------------------------------------------------
ProgrammingError Traceback (most recent call last)
<ipython-input-271-36e72f7bf30a> in <module>
12 )
13 print(query)
---> 14 cursor.execute(query)
ProgrammingError: 错误: 带相同参数类型的函数 "newcrime" 已经存在
然后创建一个触发器调用该函数:
1 2 3 4
query=('CREATE TRIGGER newcrime BEFORE INSERT OR UPDATE ON incidents FOR EACH ' 'ROW EXECUTE PROCEDURE newcrime()') cursor.execute(query) connection.commit()