Создание растра из массива numpy, принимая значения из файла csv - PullRequest
2 голосов
/ 05 ноября 2019

У меня есть геотиф. Я хочу заменить значения в растре соответствующими значениями из таблицы CSV.

Растр имеет значения класса от 0 до n, а CSV имеет вычисленное значение (например, плотность точек) для каждого класса n израстр. Я хочу создать новый растр из соответствующих значений в csv

, который я использую, используя GDAL и numpy. Я пытался с пандами, но застрял с проблемой извлечения значений из CSV в растровый кадр данных панд. Я буду выполнять это в списке растров для их соответствующих таблиц CSV.

Ниже приведен пример моих данных (один растр)

#Example raster array
[5 2 2 3
 0 3 1 4
 2 0 1 3]

#Corresponding csv table
  Class   Count  Density
    0       2       6
    1       2       9
    2       2       4
    3       3       9
    4       1       7
    5       1       2


#Output Raster (to take the corresponding density values, 
#i.e. if class = 0, then output raster = 6, the corresponding density value)
    [2 4 4 9
     6 9 9 7
     4 6 9 9]

У меня есть код для создания массива израстр и запись растра обратно из массива. Я обнаружил это на разных сайтах. Я не знаю, как создать цикл, чтобы получить значения из CSV в новом растре. Мой код цикла for ниже не является полным. Может ли кто-нибудь, пожалуйста, помогите

import numpy, sys
from osgeo import gdal
from osgeo.gdalconst import *

inRst = gdal.Open(r"c:/Raster1.tif")
band = inRst.GetRasterBand(1)
rows = inRst.RasterYSize
cols = inRst.RasterXSize
rstr_arry = band.ReadAsArray(0,0,cols,rows)

# create the output image
driver = inRst.GetDriver()
#print driver
outRst = driver.Create(r"c:/NewRstr.tif", cols, rows, 1, GDT_Int32)
outBand = outRst.GetRasterBand(1)
outData = numpy.zeros((rows,cols), numpy.int32)

for i in range(0, rows):
    for j in range(0, cols):
        if rstr_arry[i,j] =  :
            outData[i,j] = 
        elif rstr_arry[i,j] = :
            outData[i,j] = 
        else:
            outData[i,j] = 


# write the data
outRst= outBand.WriteArray(outData, 0, 0)
# flush data to disk, set the NoData value and calculate stats
outBand.FlushCache()
outBand.SetNoDataValue(-99)
# georeference the image and set the projection
outDs.SetGeoTransform(inDs.GetGeoTransform())
outDs.SetProjection(inDs.GetProjection())

1 Ответ

0 голосов
/ 06 ноября 2019

Если я не ошибаюсь в том, чего вы хотите достичь, вы сначала должны прочитать ваш CSV-файл и создать отображение значений Class в значения Density. Это можно сделать следующим образом:

import csv

mapping = {}

with open('test.csv') as csv_file:
    csv_reader = csv.DictReader(csv_file)
    for row in csv_reader:
        mapping[int(row['Class'])] = int(row['Density'])

Вы получите dict, например:

{0: 6, 1: 9, 2: 4, 3: 9, 4: 7, 5: 2}

Затем вы можете использовать np.in1d для созданияматрица маски того, что нужно заменить, и np.searchsorted для замены элементов. Перед этим вам нужно сгладить растровый массив и восстановить его форму перед записью результата. (альтернативы для замены элементов в массиве NumPy можно найти в ответах на этот вопрос: Быстрая замена значений в массиве NUMPY )

# Save the shape of the raster array
s = rstr_arry.shape
# Flatten the raster array
rstr_arry = rstr_arry.reshape(-1)
# Create 2D replacement matrix:
replace = numpy.array([list(mapping.keys()), list(mapping.values())])
# Find elements that need replacement:
mask = numpy.in1d(rstr_arry, replace[0, :])
# Replace them:
rstr_arry[mask] = replace[1, numpy.searchsorted(replace[0, :], rstr_arry[mask])]
# Restore the shape of the raster array
rstr_arry = rstr_arry.reshape(s)

Затем вы можете записать свои данные почти , как вы планировали:

outBand.WriteArray(rstr_arry, 0, 0)
outBand.SetNoDataValue(-99)

outDs.SetGeoTransform(inRst.GetGeoTransform())
outDs.SetProjection(inRst.GetProjection())

outBand.FlushCache()

Тестирование на данных вашего примера:

rstr_arry = np.asarray([
    [5, 2, 2, 3],
    [0, 3, 1, 4],
    [2, 0, 1, 3]])

mapping = {0: 6, 1: 9, 2: 4, 3: 9, 4: 7, 5: 2}

s = rstr_arry.shape
rstr_arry = rstr_arry.reshape(-1)
replace = numpy.array([list(mapping.keys()), list(mapping.values())])
mask = numpy.in1d(rstr_arry, replace[0, :])
rstr_arry[mask] = replace[1, numpy.searchsorted(replace[0, :], rstr_arry[mask])]
rstr_arry = rstr_arry.reshape(s)

print(rstr_arry)
# [[2 4 4 9]
#  [6 9 9 7]
#  [4 6 9 9]]
...