Aan het eenvoudige einde van het ETL-patronen continuüm bevindt zich het meest voorkomende formaat van allemaal - CSV, of komma-gescheiden waarden, en zijn naaste verwant, het Excel-werkblad. Enorme hoeveelheden data bewegen zich in deze formaten - makkelijk te delen, menselijk leesbaar - wat is er niet leuk aan in ArcGIS? Nou, deze dingen!
- Geen correct schema ingebouwd in het formaat
- Kolomnamen zijn vaak niet geldig in ArcGIS
- Tekstvelden met numerieke waarden worden als numeriek behandeld
- Tekstveldbreedtes worden aangenomen als 8000 (CSV) of 255 (Excel) bytes
- Gehele getalvelden kunnen als double precision float worden behandeld
- Null-waarden kunnen gecodeerd zijn met nul of een andere onwaarschijnlijke waarde
- Geometrie wordt vaak gecodeerd in een niet-ondersteund formaat voor het aanmaken van feature classes
Neem deze populaire dataset van data.gov, gespiegeld van Washingtons open dataportaal:
Eerst de data als kaart:
Washington EV Population
Nu het bron CSV-bestand:
CSV of Excel Data Problemen
In rood wijs ik enkele van deze gebruikelijke verdachte overtredingen aan. Kolomnamen bevatten spaties of metatekens, USPS-postcodes kunnen voorloopnullen hebben en moeten daarom tekst zijn, nullen zijn gebruikt om null-waarden te coderen in de kolommen Electric Range en Base MSRP, Vehicle Location is in WKT-formaat en 2020 Census Tract heeft grote gehele getallen en een naam die begint met een nummer.
De betreffende dataset heeft snelheid - hij wordt regelmatig bijgewerkt - dus als je geïnteresseerd bent om hem te gebruiken, of een van de duizenden vergelijkbare datasets - wil je het afhandelen van deze problemen automatiseren met geoprocessing.
Eerst wat onderzoek! In de blogdownload staat een scripttool die ik gebruikte om het CSV-bestand te scannen op maximale datalengtes, hier is de code:
tbl = arcpy.GetParameterAsText(0)
d = arcpy.da.Describe(tbl)
flds = [f.name for f in d['fields'] if f.type == 'String']
mDict = {f:0 for f in flds}
with arcpy.da.SearchCursor(tbl,flds) as cursor:
for row in cursor:
for f in flds:
if row[flds.index(f)]:
mDict[f] = max(mDict[f],len(row[flds.index(f)]))
for k in mDict.keys():
arcpy.AddMessage(f"""Input table '{tbl}' field '{k}' has maximum data width '{mDict[k]}'""")
Dit levert op:
Maximale Tekstveldbreedtes
Als we de Postal Code-kolom negeren, waarvan lokale kennis mij vertelt dat die 5 tekens breed is, kan ik nu de vereiste breedtes per tekstveld zien.
Ik ben nu in staat om een schema te ontwerpen dat correct omgaat met het betreffende bestand. Ik koos ModelBuilder om mijn verwerking vast te leggen omdat het kern geoprocessing en Python-functies kan omvatten die ik wil gebruiken. Het voltooide model is dit, dat we zullen doorlopen.
EVPopulation Model
De eerste stap is het opleggen van een ontworpen schema. Dit gebeurt met behulp van de veldmapcontrole in Export Table, waarbij de data feitelijk wordt gekopieerd naar een geheugen-tabel in het gewenste schema. De veldmapcontrole laat je velden hernoemen, casten en zelfs flexibel construeren.
In dit geval is er slechts één bronveld voor elk uitvoerveld, dus is de Actie altijd Eerste, en worden alleen de veld-eigenschappen aangepast.
Veldmap
Achter Export Table wordt de uitvoer-featureclass gemaakt met behulp van de geheugen-tabel als sjabloon, rijen (nog zonder geometrie) worden eraan toegevoegd, daarna wordt geometrie gemaakt uit de WKT-kolom en worden de twee velden met nul-gecodeerde null-waarden gecorrigeerd met Calculate Field-tools (let op de conditionele verwerking). Ten slotte wordt het Vehicle Location-veld verwijderd omdat het overbodig is.
Zijn we klaar? Nee! Best practice is volledige automatisering, en deze data komt van het web.
De URL die gebruikt wordt voor bestandsdownload is niet geldig als geoprocessing Text File-invoer zoals het model wil. Er bestaat ook een risico dat een gebruiker een invoer-CSV-bestand gebruikt met een andere naam dan Electric_Vehicle_Population_Data.csv, wat ertoe zou leiden dat de veldmap in Export Table terugvalt op standaard veldverwerking, waardoor al ons schema-ontwerp ongedaan wordt gemaakt.
Om zowel webdata-invoer als consistente bestandsnaam-invoer af te handelen is het model EVPopulation verpakt in een bovenliggend model, URL2EVPopulation:
URL2EVPopulation
Web Download
Eerst downloadt een Calculate Value-modeltool de actuele data naar een consistent benoemd bestand van Text File parameter type, daarna wordt het EVPopulation-model aangeroepen om de data te verwerken. Zie hoe een heel eenvoudig Python-fragment zorgt voor automatisering? 😉
Nu hebben we geautomatiseerde CSV-bestandsverwerking! Ik heb het concept "lokale bekende bestanden" iets opgerekt door data van het web te halen, maar tegenwoordig zijn bestanden via internet wél lokaal. Ik kan URL2EVPopulation op elk gewenst moment plannen of handmatig uitvoeren.
De modellen en scripttool zitten in de blogdownload.