Преобразование массива без цикла

Необходимо имеющийся массив типа 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 шт):

Автор решения: n1tr0xs

Думаю, как-то так:

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)
→ Ссылка
Автор решения: Stanislav Volodarskiy

Так как это оказалось 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)
→ Ссылка
Автор решения: Alex Alex

Можно просто использовать встроенную функцию 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)
→ Ссылка