Условные и NumPy.cumsum?
Я очень новичок в python и numpy, поэтому извините, если я злоупотребляю некоторой терминологией.
я преобразовал растр в массив 2D numpy в надежде сделать вычисления на нем быстро и эффективно.
мне нужно получить кумулятивную сумму через массив numpy такой, что для каждое значение, я генерирую сумму всех значений, которые меньше или равный этому, и запишите это значение в новый массив. Мне нужно прокатиться. через весь массив, который путь.
мне тоже нужно масштабировать выход между 1 и 100, но это кажется
более простой.
попытка уточнить на примере:
array([[ 4, 1 , 3 , 2] dtype=float32)
Я хотел бы, чтобы выходные значения (просто делая первую строку вручную) читали:
array([[ 10, 1 , 6 , 3], etc.
есть идеи, как это сделать?
спасибо заранее!
почти готовый сценарий для всех, кто заинтересован:
#Generate Cumulative Thresholds
#5/15/14
import os
import sys
import arcpy
import numpy as np
#Enable overwriting output data
arcpy.env.overwriteOutput=True
#Set working directory
os.chdir("E:/NSF Project/Salamander_Data/Continuous_Rasters/Canadian_GCM/2020/A2A/")
#Set geoprocessing variables
inRaster = "zero_eurycea_cirrigera_CA2A2020.tif"
des = arcpy.Describe(inRaster)
sr = des.SpatialReference
ext = des.Extent
ll = arcpy.Point(ext.XMin,ext.YMin)
#Convert GeoTIFF to numpy array
a = arcpy.RasterToNumPyArray(inRaster)
#Flatten for calculations
a.flatten()
#Find unique values, and record their indices to a separate object
a_unq, a_inv = np.unique(a, return_inverse=True)
#Count occurences of array indices
a_cnt = np.bincount(a_inv)
#Cumulatively sum the unique values multiplied by the number of
#occurences, arrange sums as initial array
b = np.cumsum(a_unq * a_cnt)[a_inv]
#Divide all values by 10 (reverses earlier multiplication done to
#facilitate accurate translation of ASCII scientific notation
#values < 1 to array)
b /= 10
#Rescale values between 1 and 100
maxval = np.amax(b)
b /= maxval
b *= 100
#Restore flattened array to shape of initial array
c = b.reshape(a.shape)
#Convert the array back to raster format
outRaster = arcpy.NumPyArrayToRaster(c,ll,des.meanCellWidth,des.meanCellHeight)
#Set output projection to match input
arcpy.DefineProjection_management(outRaster, sr)
#Save the raster as a TIFF
outRaster.save("C:/Users/mkcarte2/Desktop/TestData/outRaster.tif")
sys.exit()
4 ответов
в зависимости от того, как вы хотите обрабатывать повторяется, это может сработать:
In [40]: a
Out[40]: array([4, 4, 2, 1, 0, 3, 3, 1, 0, 2])
In [41]: a_unq, a_inv = np.unique(a, return_inverse=True)
In [42]: a_cnt = np.bincount(a_inv)
In [44]: np.cumsum(a_unq * a_cnt)[a_inv]
Out[44]: array([20, 20, 6, 2, 0, 12, 12, 2, 0, 6], dtype=int64)
где конечно a
является ли Ваш массив сплющенным, что вам придется изменить первоначальную форму.
и, конечно, как только numpy 1.9 выйдет, вы можете конденсировать строки 41 и 42 выше в один, быстрее:
a_unq, a_inv, a_cnt = np.unique(a, return_inverse=True, return_counts=True)
Edit:
это некрасиво, но я думаю, что это, наконец, работает:
import numpy as np
def cond_cum_sum(my_array):
my_list = []
prev = -np.inf
prev_sum = 0
for ele in my_array:
if prev != ele:
prev_sum += ele
my_list.append(prev_sum)
prev = ele
return np.array(my_list)
a = np.array([[4,2,2,3],
[9,0,5,2]], dtype=np.float32)
flat_a = a.flatten()
flat_a.sort()
temp = np.argsort(a.ravel())
cum_sums = cond_cum_sum(flat_a)
result_1 = np.zeros(len(flat_a))
result_1[temp] = cum_sums
result = result_1.reshape(a.shape)
результат:
>>> result
array([[ 9., 2., 2., 5.],
[ 23., 0., 14., 2.]])
С меньшим numpy и большим python:
a = np.array([[4,2,2,3],
[9,0,5,2]], dtype=np.float32)
np.array([[sum(x for x in arr if x <= subarr) for subarr in arr] for arr in a])
# array([[ 11., 4., 4., 7.],
# [ 16., 0., 7., 2.]])
Если сумма учитывает элементы только один раз, независимо от того, сколько они появляются, то,
np.array([[sum(set(x for x in arr if x <= subarr)) for subarr in arr] for arr in a])
# array([[ 9., 2., 2., 5.],
# [ 16., 0., 7., 2.]])
как насчет этого:
a=np.array([ 4, 1 , 3 , 2])
np.array([np.sum(a[a<=x])for x in a])
дает
array([10, 1, 6, 3])
для 2D-массива (предполагая, что вам нужна сумма всего массива, а не только строки):
a=np.array([[ 4, 1 , 3 , 2],[ 5, 1 , 3 , 2]])
np.array([[np.sum(a[a<=x])for x in a[y,:]]for y in range(a.shape[0])])
Gvies
array([[16, 2, 12, 6],
[21, 2, 12, 6]])