Записать строки и число с плавающей точкой в ​​файл ASCII с помощью Python - PullRequest
0 голосов
/ 18 декабря 2018

Я пытался объединить два массива (массив строк и массив с плавающей точкой), а затем записать окончательный массив в файл 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]) 

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Решение, которое я нашел, состояло в том, чтобы использовать библиотеку чтения и записи файлов CSV.

Я просто добавил библиотеку в начале "import csv", а затем добавил следующие строки вдоль кода.

Во-первых, в начале, мне нужно было установить каталог файлов для сохранения данных.

#Opening the file to save the data
write_path = main_directory + "\\Dados\\Exportados\\" + "file_name" + ".csv"
file = open(write_path, 'a')
writer = csv.writer(file)

Параметр 'a' позволяет добавить в конец файла

Затем на шаге, в котором я хотел сохранить данные, я добавил следующую строку:

#Writing to the file
writer.writerow([mes_pelo_nome, ano_pelo_nome, dia_pelo_nome, mascara, media]) 

В конце я добавил следующую строку, чтобы закрыть файл:

file.close()
0 голосов
/ 18 декабря 2018

По крайней мере, в том, что касается получаемой ошибки, она как бы говорит: вы пытаетесь вывести 3 столбца, но предоставляете только два формата.Если вы измените fmt arg на что-то вроде fmt=['%10s', '%10s', '%10.3f'], тогда np.savetxt должно работать.

Возможно, вы столкнетесь с другими ошибками, например, относящимися к формату / содержимому массива.Вы пытаетесь спасти.Чтобы обойти любые потенциальные ошибки, вы также можете временно добавить строку в ваш скрипт, например:

print(lista_final[:100])

прямо перед строкой np.savetxt.Таким образом, вы можете убедиться, что содержимое lista_final (по крайней мере, в первых сотнях строк) фактически соответствует ожидаемому, прежде чем пытаться обработать массив с помощью savetxt.

Edit

Когда вы вызываете np.concatenate((lista_final, lista_numpy_temporaria)) ближе к концу вашего кода, вы в конечном итоге объединяете все 3 столбца в один стандартный массив Numpy.Стандартный массив может иметь только один dtype, поэтому все, включая числа с плавающей точкой в ​​последнем столбце, в конечном итоге преобразуется в строки.Вы можете избежать этого, вместо этого объединяя ваши столбцы в массив записей (который может иметь различный тип d для каждого столбца).Скажем, три массива столбцов, которые вы пытаетесь объединить в конце вашего скрипта, выглядят так:

one = np.array(["u'espacializacao_2_1994_D1'", "u'espacializacao_2_1994_D1'",
       "u'espacializacao_2_1994_D1'", "u'espacializacao_2_1994_D1'",
       "u'espacializacao_2_1994_D1'", "u'espacializacao_2_1994_D1'",
       "u'espacializacao_2_1994_D1'", "u'espacializacao_2_1994_D1'",
       "u'espacializacao_2_1994_D1'", "u'espacializacao_2_1994_D1'",
       "u'espacializacao_2_1994_D1'"], dtype=object)

two = np.array(["u'Abiai'", "u'Camaratuba'", "u'Curimatau'", "u'Gramame'",
       "u'Guaju'", "u'Jacu'", "u'Mamanguape'", "u'Miriri'", "u'Paraiba'",
       "u'Piranhas'", "u'Trairi'"], dtype=object)

three = np.array([111.81740046, 328.11316935, 273.32344897, 223.45285225,
       393.62130737, 312.91506958, 289.06595205, 564.86507416,
       330.80016107, 328.95194289, 333.04579163])

Затем вы бы объединили их в один массив записей и затем записали их вcsv файл выглядит так:

rarr = np.rec.fromarrays([one, two, three])
np.savetxt('arcgis.csv', rarr, fmt=['%s', '%s', '%f'], delimiter=";")
...