No extremo simples do continuum dos Padrões ETL está o formato mais comum de todos - CSV, ou valores separados por vírgula, e seu primo próximo, a planilha Excel. Grandes volumes de dados circulam nesses formatos - facilmente compartilhados, legíveis por humanos - o que não gostar no ArcGIS? Bem, estas coisas!
- Não há um esquema adequado incorporado ao formato
- Os nomes das colunas frequentemente não são válidos no ArcGIS
- Campos de texto com valores numéricos são tratados como numéricos
- Larguras dos campos de texto são assumidas como 8000 (CSV) ou 255 (Excel) bytes
- Campos inteiros podem ser tratados como float de precisão dupla
- Valores nulos podem ser codificados com zero ou outro valor improvável
- A geometria frequentemente é codificada em um formato não suportado para criação de classe de feição
Pegue este conjunto de dados popular do data.gov, espelhado do portal de dados abertos de Washington:
Primeiro, os dados como um mapa:
Washington EV Population
Agora o arquivo CSV fonte:
Problemas de Dados CSV ou Excel
Em vermelho estou destacando algumas dessas violações usuais suspeitas. Nomes das colunas têm espaços ou metacaracteres, códigos postais USPS podem ter zeros à esquerda então devem ser texto, zeros foram usados para codificar nulos nas colunas Electric Range e Base MSRP, Vehicle Location está em formato WKT e 2020 Census Tract tem grandes inteiros e um nome começando com um número.
O conjunto de dados em questão tem velocidade - é atualizado regularmente - então se você estiver interessado em usá-lo, ou qualquer um dos milhares semelhantes - você vai querer automatizar o tratamento dessas questões com geoprocessamento.
Primeiro, uma pesquisa! No download do blog há uma ferramenta script que usei para escanear o arquivo CSV para larguras máximas dos dados, aqui está o código:
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]}'""")
Isto gera:
Larguras Máximas dos Campos de Texto
Ignorando a coluna Postal Code, que o conhecimento local me diz que tem 5 caracteres de largura, agora posso ver as larguras necessárias por campo de texto.
Agora estou em posição de projetar um esquema que trate corretamente o arquivo em questão. Escolhi ModelBuilder para persistir meu processamento pois ele pode envolver funções centrais de geoprocessamento e Python que planejo usar. O modelo final é este, que vamos percorrer.
Modelo EVPopulation
A primeira tarefa é impor um esquema projetado. Isso é feito usando o controle field map no Export Table, basicamente copiando os dados para uma tabela na memória no esquema desejado. O controle Field Map permite renomear, converter e até construir campos com muita flexibilidade.
Neste caso há apenas um campo fonte para cada campo de saída, então a Ação é sempre First, e apenas as propriedades do campo são manipuladas.
Field Map
A jusante do Export Table, a classe de feição de saída é criada usando a tabela na memória como modelo, linhas (ainda sem geometria) são anexadas a ela, depois a geometria é criada a partir da coluna WKT e os dois campos com nulos codificados por zero são corrigidos com ferramentas Calculate Field (note o processamento condicional). Por fim, o campo Vehicle Location é removido por ser supérfluo.
Terminamos? Não! A melhor prática é automação completa, e esses dados vêm da web.
A URL usada para download do arquivo não é válida como entrada Text File para geoprocessamento como o modelo deseja. Também há risco de um usuário usar um arquivo CSV de entrada com nome diferente de Electric_Vehicle_Population_Data.csv, o que acionaria o field map no Export Table para reverter ao tratamento padrão dos campos, desfazendo todo nosso trabalho de design do esquema.
Para lidar tanto com entrada de dados da web quanto entrada consistente pelo nome do arquivo, o modelo EVPopulation está envolvido em um modelo pai, URL2EVPopulation:
URL2EVPopulation
Download da Web
Primeiro uma ferramenta Calculate Value baixa os dados atuais para um arquivo nomeado consistentemente do tipo parâmetro Text File, depois o modelo EVPopulation é chamado para processar os dados. Veja como um trecho muito simples em Python cuida da automação? 😉
Agora temos manipulação automatizada de arquivos CSV! Estiquei um pouco o conceito de "arquivos locais bem conhecidos", alcançando a web para obter dados, mas hoje em dia arquivos pela internet são locais. Posso agendar ou executar manualmente o URL2EVPopulation quando quiser.
Os modelos e a ferramenta script estão no download do blog.