Преобразование массива без цикла
Необходимо имеющийся массив типа float преобразовать в пропорциональный, где min исходного соответствует числу 0 в новом массиве. 0 в исходном соответствует 0,5. Max исходного - соответствует 1. Нужно получить новый массив со значениями от 0 до 1 пропорциональный исходному. При том, не хотелось бы использовать очевидное решение с циклом.
def interpol(output, min_v, max_v):
if output < 0:
result = (output - min_v)/(0-min_v)*0.5
else:
result = 0.5+(output/max_v)*0.5
return result
Были мысли о map, но никак из-за дополнительных параметров. Может есть какое элегантное решение?
Ответы (3 шт):
Думаю, как-то так:
arr = list(range(50, 100))
# я так понимают мин и макс вы так получать будете
min_v = min(arr)
max_v = max(arr)
new_arr = list(map(lambda x: interpol(x, min_v, max_v), arr))
print(new_arr)
Так как это оказалось NumPy, то надо делать средствами NumPy. Получившееся функция обрабатывает как отдельные значения так и массивы любой размерности:
import numpy as np
def interpol(x, min_v, max_v):
# как же я люблю эту нотацию!
pieces = (
(x < 0, lambda x: -x / min_v),
(x >= 0, lambda x: x / max_v)
)
return (1 + np.piecewise(x, *zip(*pieces))) / 2
x = np.linspace(-2, 4, num=7, endpoint=True)
print(x)
print(interpol(x, -2, 4))
$ py numpy-example.py [-2. -1. 0. 1. 2. 3. 4.] [0. 0.25 0.5 0.625 0.75 0.875 1. ]
Если средствами чистого Питона, то труба пониже и дым пожиже. Создание интерполятора отделено от использования:
def make_interpol(min_v, max_v):
def interpol(output):
if output < 0:
result = (output - min_v)/(0-min_v)*0.5
else:
result = 0.5+(output/max_v)*0.5
return result
return interpol
interpol = make_interpol(min_v, max_v)
map(interpol, arr)
Можно просто использовать встроенную функцию np.where для условия:
import numpy as np
a=np.array([-3,-1,0,7,9])
min_a=np.min(a)
max_a=np.max(a)
ans=np.where(a<=0, (min_a-a)*.5/min_a, a*.5/max_a+.5 )
print(ans)