Level Beginner Reading 6 min Data October 2026 Programs ArcGIS
Many monitoring scripts were written for ArcMap (Python 2 and arcpy.mapping) and later migrated in a hurry to ArcGIS Pro. Anyone who leaves a government agency, or wants to run the same analysis without a license, needs to know which tool does the same thing in another program.
This article is the reference for the others: an equivalence table and the most common changes when you update an old script.
The tools side by side
The columns show the tool name (ArcGIS), the algorithm ID in QGIS (the same one used in processing.run), the PostGIS function and the geopandas method.
| Operation | ArcMap 10.x | ArcGIS Pro (arcpy) |
QGIS (Processing) | PostGIS | Python (geopandas) |
|---|---|---|---|---|---|
| Select by attribute | Select_analysis |
analysis.Select |
native:extractbyexpression |
WHERE |
gdf[gdf.year == 2025] |
| Select by location | SelectLayerByLocation_management |
management.SelectLayerByLocation |
native:extractbylocation |
WHERE EXISTS (… ST_Intersects …) |
gpd.sjoin(…, predicate="intersects") |
| Clip | Clip_analysis |
analysis.PairwiseClip |
native:clip |
ST_Intersection |
gpd.clip |
| Intersect (keeping attributes of both layers) | Intersect_analysis |
analysis.PairwiseIntersect |
native:intersection |
ST_Intersection + JOIN |
gpd.overlay(how="intersection") |
| Erase (keep what is outside) | Erase_analysis (Advanced license only) |
analysis.PairwiseErase |
native:difference |
ST_Difference |
gpd.overlay(how="difference") |
| Buffer | Buffer_analysis |
analysis.PairwiseBuffer |
native:buffer |
ST_Buffer(geom::geography, m) |
gdf.to_crs(5880).buffer(m) |
| Dissolve | Dissolve_management |
analysis.PairwiseDissolve |
native:dissolve |
ST_Union + GROUP BY |
gdf.dissolve(by=…) |
| Group nearby polygons | AggregatePolygons_cartography |
cartography.AggregatePolygons |
native:buffer + native:dissolve |
ST_ClusterDBSCAN, ST_ClusterWithin |
buffer + unary_union |
| Join a table by field | JoinField_management |
management.JoinField |
native:joinattributestable |
JOIN … USING (cnuc) |
df.merge(…) |
| Spatial join | SpatialJoin_analysis |
analysis.SpatialJoin |
native:joinattributesbylocation |
JOIN … ON ST_Intersects(…) |
gpd.sjoin |
| Summary table | Frequency_analysis |
analysis.Statistics |
qgis:statisticsbycategories |
GROUP BY |
groupby().agg() |
| Area in hectares | !shape.geodesicArea@hectares! |
CalculateGeometryAttributes (AREA_GEODESIC) |
$area / 10000 (ellipsoidal) |
ST_Area(geom::geography) / 10000 |
to_crs("ESRI:102033").area / 10000 |
| Polygon → point | FeatureToPoint_management |
management.FeatureToPoint (INSIDE) |
native:pointonsurface |
ST_PointOnSurface |
representative_point() |
| Repair geometry | RepairGeometry_management |
management.RepairGeometry |
native:fixgeometries |
ST_MakeValid |
make_valid() |
| Kernel density | sa.KernelDensity |
sa.KernelDensity |
native:heatmapkerneldensityestimation |
grid + weighted sum | numpy |
| Zonal statistics | sa.ZonalStatisticsAsTable |
sa.ZonalStatisticsAsTable |
native:zonalstatisticsfb |
ST_SummaryStats (postgis_raster) |
rasterstats.zonal_stats |
| Delete and append records | DeleteFeatures + Append |
DeleteFeatures + Append |
save over the layer | DELETE + INSERT, ON CONFLICT |
to_postgis(if_exists=…) |
| Map series | arcpy.mapping (.mxd) |
arcpy.mp (.aprx), map series |
Atlas | not applicable | loop with matplotlib |
In ArcGIS Pro, the Pairwise… tools (Clip, Intersect, Erase, Dissolve, Buffer) use parallel processing and are usually much faster than the classic ones. For the overlays in these articles, the result is the same.
Each program in one sentence
- ArcGIS Pro
-
Paid.
arcpycomes with it and runs in ArcGIS’s own Python. Good when the institution already has a license and publishes to ArcGIS Online. - QGIS
-
Free. Everything you do in the menus is a Processing algorithm that can be called from the Python console (
processing.run), from graphical models or from the terminal (qgis_process). - PostGIS
- Free. Best when the data is large, lives in a database and the analysis is repeated every week. The result is ready for Power BI.
- Python (geopandas)
- Free. Good for automating without opening any program and for making charts and maps. For very large data, leave the heavy overlays to PostGIS.
Updating an old ArcMap script
ArcMap scripts use Python 2.7. ArcGIS Pro uses Python 3. The changes that show up most often:
| In the old script | In ArcGIS Pro | Why |
|---|---|---|
print "text" |
print("text") |
Python 3 |
arcpy.SearchCursor(fc) and row.getValue("field") |
arcpy.da.SearchCursor(fc, ["field"]) |
da cursors are much faster |
arcpy.mapping.MapDocument("x.mxd") |
arcpy.mp.ArcGISProject("x.aprx") |
.mxd does not exist in Pro (import it with Insert → Import Map) |
arcpy.mapping.ExportToJPEG(mxd, …) |
layout.exportToJPEG(…) |
exporting is now done by the layout |
"PYTHON_9.3" in CalculateField |
"PYTHON3" |
the expression type changed |
"in_memory\\x" |
"memory\\x" |
Pro’s in-memory workspace |
.tbx toolbox |
.atbx |
Pro still opens .tbx but saves .atbx |
| files with accents in ISO-8859-1 | save as UTF-8 | Python 3 reads UTF-8 by default |
- Functions named
maxandminthat override Python’s own and sort the whole list on every row read. With 100,000 rows, the script grinds to a halt. Use Python’s built-inmax()over the cursor, or the Statistics tool. - Comma as decimal separator in text parameters (
"0,0015") mixed with a period ("0.0015") in the same script. The result changes with the Windows language. Pass numbers as numbers, not text. - Network paths and passwords written in the code. Read paths from tool parameters (
GetParameterAsText) and passwords from environment variables or a file outside the script. Module 6 (in Portuguese) shows how.
From an ArcGIS script tool to a QGIS script
In ArcGIS, a script becomes a tool by reading parameters with arcpy.GetParameterAsText(0). In QGIS, the equivalent is a Processing script, which shows up in the Toolbox with its own form. Variable names in the code are in Portuguese, as in the original scripts (entrada = input, saida = output, ucs = protected areas).
import arcpy
entrada = arcpy.GetParameterAsText(0) # alerts layer
ucs = arcpy.GetParameterAsText(1) # protected area boundaries
saida = arcpy.GetParameterAsText(2) # output layer
arcpy.analysis.PairwiseIntersect([entrada, ucs], saida)
arcpy.AddMessage("Done.")In the toolbox: right-click → New → Script Tool, and declare the three parameters.
Save it in Toolbox → Scripts → Create New Script:
from qgis.processing import alg
import processing
@alg(name="alertas_em_ucs", label="Alerts in protected areas", group="monitoramento",
group_label="Monitoring")
@alg.input(type=alg.SOURCE, name="ENTRADA", label="Alerts layer")
@alg.input(type=alg.SOURCE, name="UCS", label="Protected area boundaries")
@alg.input(type=alg.SINK, name="SAIDA", label="Alerts in protected areas")
def alertas_em_ucs(instance, parameters, context, feedback, inputs):
"""Intersects the alerts with the protected areas, keeping the attributes of both layers."""
resultado = processing.run("native:intersection", {
"INPUT": parameters["ENTRADA"], "OVERLAY": parameters["UCS"],
"OUTPUT": parameters["SAIDA"]}, context=context, feedback=feedback)
return {"SAIDA": resultado["OUTPUT"]}In the database, the “tool” is a query saved as a view (or a SQL function):
CREATE OR REPLACE VIEW alertas_em_ucs AS
SELECT a.*, u.cnuc, u.nome_uc,
ST_Intersection(a.geom, u.geom) AS geom_uc
FROM artigos.deter a
JOIN artigos.ucs u ON ST_Intersects(a.geom, u.geom);A script with command-line arguments:
import sys
import geopandas as gpd
entrada, ucs, saida = sys.argv[1:4]
alertas = gpd.read_file(entrada)
limites = gpd.read_file(ucs).to_crs(alertas.crs)
gpd.overlay(alertas, limites, how="intersection").to_file(saida)python alertas_em_ucs.py deter.gpkg ucs.gpkg alertas_ucs.gpkgThe tabs above are synchronized across all articles: pick your program once and the other articles open on it.
Next articles
The following articles put this table into practice, always with the four versions. Start with Inside and around protected areas.
Updates
- 2026-10-29: first published, with data from INPE, MMA, IBAMA and SICAR from October 2026.
Reuse
Citation
@misc{alves2026,
author = {Alves, Hendesson},
publisher = {Hendesson Alves},
title = {From {ArcMap} to {QGIS:} The Same Tool in Every Program},
date = {2026-10-29},
url = {https://hendesson.github.io/en/articles/01-equivalences.html},
doi = {10.5281/zenodo.23780245},
langid = {en},
abstract = {Still running ArcMap scripts, or want to stop depending on
a license? This article gives the equivalence table between ArcMap,
ArcGIS Pro, QGIS, PostGIS and geopandas for the most common
geoprocessing tools, plus the changes almost every old script needs
to run today.}
}