En una publicación anterior me inicié usando DuckDB en un cuaderno alojado en ArcGIS Online. Esa publicación destacó la lectura de archivos GeoParquet en un object store para mantener un servicio de entidades. Ese es un flujo de trabajo poderoso pero es mucho más probable que tu trabajo diario implique manejar formatos de archivo comunes que consumen demasiado tiempo para ingerir, como CSV, Excel y JSON. Esta publicación trata sobre facilitar tu vida mostrando cómo DuckDB habilita SQL para cualquier formato de archivo y también soporta conversión simple a formatos Esri. Si tienes habilidades básicas en SQL y Python - es decir, puedes leer este ejemplo y la ayuda web - estarás bien.<\/P>
Aquí hay algo en acción en vivo, incidentes abiertos 311 de Bloomington Indiana migrados a una clase de entidad en segundos.<\/P>
Incidentes 311 de Bloomington<\/span><\/span><\/P> <\/P>El cuaderno (en la descarga del blog) lee un archivo CSV desde una URL pública y escribe una clase de entidad en la geodatabase predeterminada del proyecto. Los cuadernos son un buen lugar para comenzar comparado con una herramienta de script porque puedes trabajar interactivamente en una celda mientras descubres tu SQL. Una vez que todo funcione podrías copiar el código a una herramienta de script para automatización fácil y programada.<\/P>Pero primero necesitas instalar DuckDB! La ruta habitual para agregar un paquete Python a tu entorno es clonar el entorno arcgispro-py3 y luego agregar un paquete en la interfaz del Administrador de Paquetes backstage en Pro. Buscarías un paquete llamado python-duckdb. Esto me dio error (sucede) así que hice una instalación manual. Cloné mi entorno predeterminado a uno que nombré arcgispro-py3-quack e instalé DuckDB abriendo el Símbolo del sistema de Python desde el grupo de programas ArcGIS y ejecutando este comando ('username' será el tuyo):<\/P> <\/P>conda install -c conda-forge python-duckdb=1.0.0 -p "C:\Users\username\AppData\Local\ESRI\conda\envs\arcgispro-py3-quack" --yes<\/code><\/pre> <\/P>Asegúrate de obtener la última distribución DuckDB, al momento de escribir es la 1.0.0.<\/P>Vamos a recorrer cada celda del cuaderno. La primera es bastante simple, las importaciones y algunas llamadas a duckdb para configurar el entorno.<\/P> <\/P># Importaciones, entorno
import arcpy
import duckdb
from arcgis.features import GeoAccessor, GeoSeriesAccessor
import os
import requests
from urllib.parse import urlparse
conn = duckdb.connect()
conn.sql("install spatial;load spatial;")
conn.sql("install httpfs;load httpfs;")
conn.sql("set s3_region='us-west-2';")
conn.sql("set enable_object_cache=true;")
arcpy.env.overwriteOutput = True<\/code><\/pre> <\/P>La segunda celda crea un dataframe pandas leyendo los datos CSV mientras infiera automáticamente los tipos de datos, una gran ayuda. Notarás que programo defensivamente para la situación en que el servidor al que accedo no soporta acceso HTTP range request como DuckDB requiere - descargo los datos - lo cual fue necesario en este caso.<\/P> <\/P># Leer datos en duckdb
url = r'https://data.bloomington.in.gov/resource/aw6y-t4ix.csv?$limit=200000'
filename = os.path.basename(urlparse(url).path)
base, extension = os.path.splitext(filename)
try:
sql = "create or replace view bloomington311_view as select * from read_csv_auto('{}');".format(url)
conn.sql(sql)
except:
response = requests.get(url)
with open(filename, 'w', encoding="utf-8") as f:
f.write(response.text)
f.close()
sql = "create or replace view bloomington311_view as select * from read_csv_auto('{}');".format(filename)
conn.sql(sql)
# Construye la consulta SQL que deseas para renombrar, convertir o procesar los datos.
# Este conjunto tiene una columna en WKT ya, si tus datos no tienen entonces necesitarás
# crear una usando las funciones ST_ en DuckDB.
sql = """select service_request_id, requested_datetime, updated_datetime, closed_date, status_description, source,
service_name, description, agency_responsible, address, city, state, try_cast (zip as varchar(10)) as zip, sladays,
request_complete_days, sla_diff_days,
geocoded_column as SHAPE from bloomington311_view where SHAPE is not null;"""
df = conn.sql(sql).df()<\/code><\/pre> <\/P>Nótese el punto sobre usar o crear valores WKT para tu geometría. La extensión espacial para DuckDB tiene un conjunto rico de funciones espaciales.<\/P>Ahora convierte el dataframe a una clase de entidad. Tienes otras opciones de conversión. Nota que la API Python arcgis no sabe de dónde vino el dataframe - ¡DuckDB funcionará bien! - así que habilito espacialmente el dataframe y luego escribo a una clase de entidad en la geodatabase. No hay necesidad de manipular propiedades de campos atributo, simplemente funcionan (ver el SQL arriba, surgió la clásica situación de convertir códigos ZIP a texto).<\/P> <\/P># Escribir la clase de entidad
df.spatial.set_geometry("SHAPE",sr=4326,inplace=True)
aprx = arcpy.mp.ArcGISProject("CURRENT")
gdb = aprx.defaultGeodatabase
out_fc = arcpy.ValidateTableName(base,gdb)
location = os.path.join(gdb,out_fc)
df.spatial.to_featureclass(location)<\/code><\/pre> <\/P>Finalmente, anuncio!<\/P> <\/P>print("Created feature class {}".format(location))<\/code><\/pre> <\/P>Eso es todo, migración rápida, simple e inteligente de datos con algo de ayuda de DuckDB!<\/P>El cuaderno está en la descarga del blog, cuéntanos cómo te va.<\/P>