cd658cc703
Tres funciones puras nuevas del dominio datascience (tags eda + geospatial) que
sostienen el capítulo GEOSPATIAL del AutomaticEDA, delegadas a fn-constructor:
- detect_latlon_columns: identifica el par (lat, lon) por nombre de columna +
rango de valores ([-90,90] / [-180,180]) desde profile['columns']. Devuelve
{lat_col, lon_col, confidence, reason}. 9 tests.
- analyze_geo_extent: bbox, centroide, span haversine, conteo por zona/país
(lookup offline con bounding boxes embebidos, KISS sin geopandas) y
hemisferios. 7 tests.
- build_geo_scatter: prepara los puntos del scatter en orden [lon, lat] con
downsampling determinista por paso fijo + aspect equirectangular 1/cos(lat)
clampado. 6 tests.
Registradas en datascience/__init__.py. Todas pure, params_schema completo,
.md autosuficiente (Ejemplo + Cuando usarla + Gotchas).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.5 KiB
5.5 KiB
name, id, kind, lang, domain, version, purity, signature, description, tags, params, output, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, file_path
| name | id | kind | lang | domain | version | purity | signature | description | tags | params | output | uses_functions | uses_types | returns | returns_optional | error_type | imports | tested | tests | test_file_path | file_path | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| detect_latlon_columns | detect_latlon_columns_py_datascience | function | py | datascience | 1.0.0 | pure | def detect_latlon_columns(columns: list, samples: dict | None = None) -> dict | Detecta un par (latitud, longitud) entre las columnas de un TableProfile del grupo eda combinando heuristica de nombre (latitude/longitude/lat/lon/lng + x/y debiles) con validacion de rango obligatoria (latitud en [-90,90], longitud en [-180,180]). Lee defensivamente con .get; NUNCA lanza. Usa el sub-bloque numeric.min/max o, si falta, la lista de samples opcional. Devuelve SIEMPRE un dict {lat_col, lon_col, confidence, reason}; si no hay par valido, las columnas van a None y confidence a 0.0. |
|
|
Dict SIEMPRE presente con la forma {lat_col: str|None, lon_col: str|None, confidence: float en [0,1], reason: str en espanol}. En exito, lat_col y lon_col nombran columnas distintas; confidence ~1.0 para par con nombre fuerte (latitude/longitude/lat/lon/lng) + rango valido y ~0.7 para par debil (x/y) + rango. En fallo, ambas columnas None, confidence 0.0 y reason explica por que (sin columnas, nombre sin match, rango fuera de bounds, falta uno de los dos ejes...). | false | true |
|
python/functions/datascience/detect_latlon_columns_test.py | python/functions/datascience/detect_latlon_columns.py |
Ejemplo
import sys, os
sys.path.insert(0, os.path.join("python", "functions"))
from datascience.detect_latlon_columns import detect_latlon_columns
# Columnas tal y como vienen en profile['columns'] de un TableProfile del grupo eda:
columns = [
{"name": "id", "inferred_type": "numeric", "numeric": {"min": 1, "max": 9999}},
{"name": "latitude", "inferred_type": "numeric", "numeric": {"min": -45.0, "max": 45.0}},
{"name": "longitude", "inferred_type": "numeric", "numeric": {"min": -120.0, "max": 120.0}},
]
res = detect_latlon_columns(columns)
print(res["lat_col"], res["lon_col"], res["confidence"])
# latitude longitude 1.0
# Sin bloque numeric, validando el rango con samples:
cols2 = [{"name": "lat"}, {"name": "lon"}]
samples = {"lat": [10.5, 20.0, 30.25], "lon": [-40.0, 50.5, 60.0]}
print(detect_latlon_columns(cols2, samples)["lat_col"]) # lat
Cuando usarla
- Usala al perfilar una tabla en
AutomaticEDApara decidir si tiene geometria de puntos: cuandodetect_latlon_columnsdevuelve un par conconfidencealta, el capitulo geospatial puede dibujar un mapa, calcular un bounding box o proponer un cluster espacial. - Antes de un analisis geoespacial (alpha shape, convex hull, joins por proximidad) para localizar automaticamente que columnas son la latitud y la longitud sin pedirlo al usuario.
- Cuando recibas un
TableProfiledel grupoeday quieras enrutar columnas a sub-analisis por tipo semantico: este es el detector del par lat/lon, complementario ainfer_semantic_type.
Gotchas
- Funcion pura, sin I/O y determinista. Lectura defensiva con
.get: NUNCA lanza. Cualquier input malformado (None, no-lista, entradas no-dict, claves ausentes) devuelve el dict de fallo conlat_col/lon_colen None yconfidence0.0. - El nombre solo no basta: una columna
latitudecuyo rango se sale de[-90, 90]se descarta (no es coordenada real). Igual paralongitudefuera de[-180, 180]. La validacion de rango es obligatoria. - El rango de latitud
[-90, 90]es un subconjunto del de longitud[-180, 180], por eso el nombre es necesario para desambiguar cual eje es cual; una columna numerica en[-90, 90]sin nombre que sugiera lat/lon no se detecta. - Los nombres genericos
x/y(yx_coord/y_coord) son candidatos debiles: solo forman par si el rango encaja y existe la otra mitad (unx/lonpara lay, uny/latpara lax). Unysuelto sin pareja devuelve None. - Requiere AMBOS ejes para considerar exito. Si solo encuentra latitud o solo longitud, devuelve el dict de fallo (no media coordenada).
samplessolo se consulta cuando faltanumeric.min/numeric.max. Si una columna trae el bloque numeric, ese manda aunque pases samples para ella.- El matching de nombre es por subcadena normalizada (se quitan
_,-y espacios), asi que nombres comoplate(contiene "lat") podrian marcarse como candidatos por nombre — pero solo pasarian si su rango cae en[-90, 90]y hay una longitud pareja, filtro que en la practica descarta los falsos positivos.