Я пытался объединить два массива (массив строк и массив с плавающей точкой), а затем записать окончательный массив в файл CSV.Тем не менее, я столкнулся с множеством проблем, чтобы решить ее.Я уже пробовал много учебников в Интернете на эту тему, но никто не работал должным образом для меня.
Код, который я пишу, использует python для автоматизации серии задач в ArcGIS.После запуска кода и получения всех средних значений мне нужно объединить среднее значение из растрового файла вместе с двумя строками.
Я уже пытался объединить всю необходимую информацию в одном массиве, но у меня возникают проблемы при попытке сохранить его в файл CSV.
Код следующий.
#Interpolation
arcpy.gp.Idw_sa(out_Layer_shp, i_dia, arcpy.env.workspace + "\\Raster\\" + out_Layer_tif + ".tif", tamanho_celula, potencia_idw, "VARIABLE 12 12", "")
#Deleting the shape file
arcpy.Delete_management(out_Layer_shp, "")
lista_final = np.array([], dtype = object) #Final list
contador = 0 #Counter
for mascara in bacias: #Importing shapefiles to clip the interpolated raster
importar_camada = arcpy.env.workspace + "\\Shapefile\\Bacias\\" + mascara + ".shp"
arcpy.MakeFeatureLayer_management(importar_camada, mascara)
#Variable to set the name of the layers that will be created and then clipped
camada_para_recortar = out_Layer_tif + ".tif"
camada_resultante = out_Layer + "_recortada"
nome_do_raster = camada_resultante + "_" + mascara + ".tif"
#Code to interpolate
arcpy.Clip_management(camada_para_recortar, "", arcpy.env.workspace + "\\Raster\\Recortes\\" + camada_resultante + "_" + mascara + ".tif", mascara, "-3,402823e+038", "ClippingGeometry", "NO_MAINTAIN_EXTENT")
#Getting the mean value from the raster clipped
media = arcpy.GetRasterProperties_management (nome_do_raster, "MEAN", "")
lista_strings = np.array([out_Layer, mascara]) #array string
lista_medias = np.array([media]) #float string
arquivo_com_as_medias = "medias 01" #Name of the file to save the means values
lista_numpy_temporaria = np.array([out_Layer, mascara, media], dtype = object) #Temporary list to save the data before
#it be added to the final array
#lista_numpy_temporaria = lista_numpy_temporaria.reshape(1,3)
lista_final = np.concatenate((lista_final, lista_numpy_temporaria)) #Concatenating the two arrays
contador = contador + 1 #Incrementing the counter
lista_final = lista_final.reshape(contador,3) #reshape the final array
np.savetxt(arcpy.env.workspace + "\\Dados\\Exportados\\" + arquivo_com_as_medias + ".csv", lista_final, fmt="%10s %10.3f", delimiter=";", header = "#1, #2")
#Attempt to write the arrays based in a tutorial that I found, but it didn't work
"""
ab = np.zeros(lista_numpy_temporaria.size, dtype=[('var1', 'U6'), ('var2', float)])
ab['var1'] = lista_strings
ab['var2'] = lista_medias
np.savetxt(arcpy.env.workspace + "\\Dados\\Exportados\\" + arquivo_com_as_medias + ".csv", ab, fmt="%10s %10.3f")
"""
print(lista_final)
Сообщение об ошибке, полученное из этого кода, следующее
Ошибка времени выполнения Traceback (последний вызов был последним): файл "", строка 50, в файле "C: \ Python27 \ ArcGIS10.3 \ lib \ site-packages \ numpy \ lib \ npyio.py", строка 1031, в savetxt выдается ошибка ValueError: fmt имеет неверное количество форматов%:% 10s% 10.3f
В коде много комментариев из-за множества попыток, которые я предпринялизготовление.
Я хочу получить CSV-файл с 3 столбцами и множеством строк, количество строк будет варьироваться в зависимости от количества интерполированных данных.Один пример может быть следующим:
RASTER FILE SUB_BASIN MEAN_VALUE
out_Layer mascara 99.99
Спасибо.
Редактировать 1
Новое сообщение об ошибке после предложенного решения следующее:
Ошибка времени выполнения Traceback (последний вызов был последним): файл "", строка 210, в файле "C: \ Python27 \ ArcGIS10.3 \ lib \ site-packages \ numpy \ lib \ npyio.py ", строка 1047, в savetxt fh.write (asbytes (format% tuple (row) + newline)) TypeError: необходим аргумент с плавающей точкой, а не результат
Решение, которое я нашел, состояло в том, чтобыизмените формат с fmt = "% 10s% 10s% 10.3f" на этот
fmt="%10s %10s %10s"
Хотя это не лучшее решение, так как оно возвращает числав виде строк.
Полный код, который я использую, следующий:
import arcpy
import numpy as np
from arcpy import sa
from arcpy.sa import *
from calendar import monthrange
# Set environment settings
arcpy.env.workspace = "C:\\Projetos\\ArcGIS\\Teste9"
arcpy.env.overwriteOutput = True
#get the map document
mxd = arcpy.mapping.MapDocument("CURRENT")
#get the data frame
df = arcpy.mapping.ListDataFrames(mxd,"la*")[0]
#Months and years to interpolate
mes = ["2"] #Months
ano = ["1994"] #Years
#Days to interpolate based in the month lenght
coluna_interpolada_28 = ["D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15", "D16", "D17", "D18", "D19", "D20", "D21", "D22", "D23", "D24", "D25", "D26", "D27", "D28"]
coluna_interpolada_29 = ["D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15", "D16", "D17", "D18", "D19", "D20", "D21", "D22", "D23", "D24", "D25", "D26", "D27", "D28", "D29"]
coluna_interpolada_30 = ["D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15", "D16", "D17", "D18", "D19", "D20", "D21", "D22", "D23", "D24", "D25", "D26", "D27", "D28", "D29", "D30"]
coluna_interpolada_31 = ["D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15", "D16", "D17", "D18", "D19", "D20", "D21", "D22", "D23", "D24", "D25", "D26", "D27", "D28", "D29", "D30", "D31"]
#Interpolation extent
arcpy.env.extent = arcpy.env.workspace + "\\Shapefile\\" + "PB.shp"
#Final list
lista_final = np.array([], dtype = object)
#Counter that is going to be used to reshape the arrays
contador = 0
#Loop to go through the time series
for i_ano in ano: #For loop with the years
for i_mes in mes: #For loop with the months
#Month Range
quantidade_dias = monthrange(int(i_ano), int(i_mes))
#If clauses to define which columns it is goin to interpolate
if quantidade_dias == (1, 28):
coluna_interpolada = coluna_interpolada_28
elif quantidade_dias == (1, 29):
coluna_interpolada = coluna_interpolada_29
elif quantidade_dias == (1, 30):
coluna_interpolada = coluna_interpolada_30
else:
coluna_interpolada = coluna_interpolada_31
#For loop with the days
for i_dia in coluna_interpolada:
tabela = i_mes + "_" + i_ano #Exemplo "2_1994"
in_Table = arcpy.env.workspace + "\\Dados\\" + tabela + ".csv" #Exemplo "2_1994.csv"
x_coords = "LONG"
y_coords = "LAT"
z_coords = "POINT_Z"
out_Layer = "espacializacao" + "_" + tabela + "_" + i_dia #nome da camada "lyr" que vai ser criada
#NOME DO ARQUIVO QUE VAI SER SALVO. Exemplo "espacializacao_2_1994_D2"
out_Layer_shp = out_Layer + "_shp" #nome da camada "shp" que vai ser criada
out_Layer_tif = out_Layer + "_tif"
tamanho_celula = "0,10" #precisar por as aspas, apesar de ser um número
potencia_idw = "2" #precisa por as aspas, apesar de ser um número
raio_de_busca = RadiusVariable(12, 12) #Critério para fazer a interpolação, raio variando até 12 quilômetros até conseguir englobar 12 pontos
# Set the spatial reference
spRef = arcpy.SpatialReference("WGS 1984")
#Create event layer
arcpy.MakeXYEventLayer_management(in_Table, x_coords, y_coords, out_Layer, spRef, "")
#Exporting event layer as shapefile
arcpy.FeatureToPoint_management(out_Layer, arcpy.env.workspace + "\\" + "Shapefile\\Exportados\\" + out_Layer_shp + ".shp","")
#Layer that is going to be deleted "lyr"
lyr = arcpy.mapping.ListLayers(mxd, "espacializacao",df)
#Deleting the layer
for df in arcpy.mapping.ListDataFrames(mxd):
for lyr in arcpy.mapping.ListLayers(mxd, "", df): #O parâmetro que não foi passado foi o WildCard, não precisa
if lyr.name == out_Layer:
arcpy.mapping.RemoveLayer(df, lyr) #Removendo a camada da paleta lateral
#Some variables to define some parameters to the software
camada_editando = out_Layer_shp
coluna_criada = "Media"
tipo_campo = "FLOAT"
precisao_campo = ""
precisao_decimais = ""
comprimento_campo = 50 #Tamanho qualquer suposto
arcpy.AddField_management(camada_editando, coluna_criada, "LONG", precisao_campo,
precisao_decimais, comprimento_campo, "", "NULLABLE",
"NON_REQUIRED", "")
bacias = ["Abiai", "Camaratuba", "Curimatau", "Gramame", "Guaju", "Jacu", "Mamanguape", "Miriri", "Paraiba", "Piranhas", "Trairi"]
#Code to interpolate
arcpy.gp.Idw_sa(out_Layer_shp, i_dia, arcpy.env.workspace + "\\Raster\\" + out_Layer_tif + ".tif", tamanho_celula, potencia_idw, "VARIABLE 12 12", "")
#Deleting shapefile
arcpy.Delete_management(out_Layer_shp, "")
#For loop to clip the raster file using the shapefiles
for mascara in bacias:
importar_camada = arcpy.env.workspace + "\\Shapefile\\Bacias\\" + mascara + ".shp" #Importing shapefile to clip
arcpy.MakeFeatureLayer_management(importar_camada, mascara)
#Some variables defining some parameters to using in the clip function
camada_para_recortar = out_Layer_tif + ".tif"
camada_resultante = out_Layer + "_recortada"
nome_do_raster = camada_resultante + "_" + mascara + ".tif"
#Function to clip the raster file
arcpy.Clip_management(camada_para_recortar, "", arcpy.env.workspace + "\\Raster\\Recortes\\" + camada_resultante + "_" + mascara + ".tif", mascara, "-3,402823e+038", "ClippingGeometry", "NO_MAINTAIN_EXTENT")
media = arcpy.GetRasterProperties_management (nome_do_raster, "MEAN", "")
lista_strings = np.array([out_Layer, mascara])
lista_medias = np.array([media])
#Name of the file to save the means values
arquivo_com_as_medias = "medias 01"
lista_numpy_temporaria = np.append(lista_strings, lista_medias)
lista_final = np.concatenate((lista_final, lista_numpy_temporaria))
#Deleting the raster clipped
arcpy.Delete_management(nome_do_raster, "")
#Counter
contador = contador + 1
print(lista_final)
#Reshaping the file
lista_final = lista_final.reshape(contador,3)
print(lista_final)
#Saving the arrays to a CSV file
np.savetxt(arcpy.env.workspace + "\\Dados\\Exportados\\" + arquivo_com_as_medias + ".csv", lista_final, fmt="%10s %10s %10s", delimiter=";", header = "")
#Deleting the original raster
arcpy.Delete_management(out_Layer_tif + ".tif", "")
Используя этот код выше, "print (lista_final)" возвращает следующее:
>>> print(lista_final)
[[u'espacializacao_2_1994_D1' u'Abiai' u'111,81740045547']
[u'espacializacao_2_1994_D1' u'Camaratuba' u'328,11316935221']
[u'espacializacao_2_1994_D1' u'Curimatau' u'273,3234489704']
[u'espacializacao_2_1994_D1' u'Gramame' u'223,45285224915']
[u'espacializacao_2_1994_D1' u'Guaju' u'393,62130737305']
[u'espacializacao_2_1994_D1' u'Jacu' u'312,91506958008']
[u'espacializacao_2_1994_D1' u'Mamanguape' u'289,06595204671']
[u'espacializacao_2_1994_D1' u'Miriri' u'564,86507415771']
[u'espacializacao_2_1994_D1' u'Paraiba' u'330,80016106998']
[u'espacializacao_2_1994_D1' u'Piranhas' u'328,95194289264']
[u'espacializacao_2_1994_D1' u'Trairi' u'333,04579162598']]
Еще одна вещь, о которой я думал, было ли это лучшим подходом для записи этих выходных данных в файл CSV?Потому что я уже видел некоторые учебники, использующие «модуль CSV» для записи непосредственно в файлы CSV.Однако я уже попробовал это безуспешно.
Я говорю это, потому что этот код будет повторяться много раз, что-то вроде 19.000 раз.Потому что я использую его для интерполяции ежедневных данных о количестве осадков за 54 года.Итак, я думаю, что массив такого размера не является хорошим подходом для решения этой проблемы.
Еще раз спасибо.
Редактировать 2
Я попробовал то, что вы предложили, но все равно не работает.Я сделал следующие изменения:
#First attempt
one = np.array([out_Layer], dtype = object)
two = np.array([mascara], dtype = object)
three = np.array([media])
rarr = np.rec.fromarrays([one, two, three])
arquivo_com_as_medias = "medias 01" #File with the means values
csv_directory = arcpy.env.workspace + "\\Dados\\Exportados\\" + arquivo_com_as_medias + ".csv"
np.savetxt(csv_directory, rarr, fmt=['%s', '%s', '%f'], delimiter=";")
И теперь отображается сообщение об ошибке:
Ошибка времени выполнения Traceback (последний вызов был последним): Файл "", строка 176,в файле "C: \ Python27 \ ArcGIS10.3 \ lib \ site-packages \ numpy \ core \ records.py", строка 560, во всплывающих окнах выведите ValueError ("несоответствие формы массива в массиве% d"% k) ValueError:несоответствие формы массива в массиве 2
Код в строке 176:
rarr = np.rec.fromarrays([one, two, three])