Python: назначить метки значениям в массиве - PullRequest
0 голосов
/ 20 февраля 2019

У меня есть массив, который представляет некоторые данные временных рядов:

array([[[-0.59776013],
    [-0.59776013],
    [-0.59776013],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [ 0.31863936],
    [ 0.31863936],
    [ 0.31863936],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [ 0.59776013],
    [ 0.59776013],
    [ 0.59776013],
    [ 0.93458929],
    [ 0.93458929],
    [ 0.93458929],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [-0.06270678],
    [-0.06270678],
    [-0.06270678],
    [-0.06270678],
    [-0.06270678],
    [-0.06270678],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [ 0.75541503],
    [ 0.75541503],
    [ 0.75541503],
    [ 0.93458929],
    [ 0.93458929],
    [ 0.93458929],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [ 0.75541503],
    [ 0.75541503],
    [ 0.75541503],
    [-0.31863936],
    [-0.31863936],
    [-0.31863936],
    [ 0.31863936],
    [ 0.31863936],
    [ 0.31863936],
    [ 0.        ],
    [ 0.        ],
    [ 0.        ],
    [ 0.        ],
    [ 0.        ],
    [ 0.        ],
    [ 0.        ],
    [ 0.        ]]])

Уникальные значения в этом массиве:

np.unique(sax_dataset_inv)
array([-0.59776013, -0.31863936, -0.06270678,  0.        ,  0.31863936,
    0.59776013,  0.75541503,  0.93458929])

Моя задача

Назначьте либо «F» для быстрого, «S» для медленного или «M» для среднего значения данного массива.

Моя попытка

Iможет сделать это для 2 назначений, 'F' или 'S':

sax_list = ['F' if element < 0 else 'S' for element in list(sax_dataset_inv.flatten())]

Однако я не могу понять, как я могу сделать то же самое выражение выше для 3 различных меток.

Требуемый вывод

Возьмите пример массива [-3-2-1,0,1,2,3,4,5,6]

Значения от -3 до -1 включительно должен быть присвоен «F».Значения от 0 до 3 включительно должны быть присвоены «М».Значениям больше 3 следует присвоить 'S'.

Ответы [ 4 ]

0 голосов
/ 20 февраля 2019

Используйте numpy.select для векторизованного решения:

new_arr = np.select([arr>3, (arr>=-3) & (arr<=-1), (arr>=0)&(arr<=3)],
                    ['S','F','M'], 
                    default='')
print (new_arr)

['F' 'F' 'F' 'M' 'M' 'M' 'M' 'S' 'S' 'S']

Производительность :

arr = np.array([-3,-2,-1,0,1,2,3,4,5,6] * 1000)

my_list = [-3,-2,-1,0,1,2,3,4,5,6] * 1000

In [276]: %timeit my_list_mapping = ['F' if ((i >= -3) & (i <= -1)) else 'M' if ((i >= 0) & (i <= 3)) else 'S' for i in my_list]
1.14 ms ± 67.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [277]: %timeit np.select([arr>3, (arr>=-3) & (arr<=-1), (arr>=0)&(arr<=3)],['S','F','M'],  default='')
172 µs ± 7.35 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
0 голосов
/ 20 февраля 2019

Примечание: Интервалы OP равны [-3,-1], [0,3] & (3,..), поэтому я предполагаю только целые значения.Условия могут быть изменены соответствующим образом, но дизайн остается.

Использование list comprehensions для if-elif-else:

my_list = [-3,-2,-1,0,1,2,3,4,5,6]

my_list_mapping = ['F' if ((i >= -3) & (i <= -1)) else 'M' if ((i >= 0) & (i <= 3)) else 'S' for i in my_list]
print(my_list_mapping)
    ['F', 'F', 'F', 'M', 'M', 'M', 'M', 'S', 'S', 'S']
0 голосов
/ 20 февраля 2019

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

    def mapping_function(value):
        if value >= -3 and value <= -1:
            return 'F'
        elif value >= 0 and value <= 3:
            return 'M'
        elif value > 3:
            return 'S'
        else:
            return 'U'  # eg. as undefined
    my_array = [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6]
    mapped_vals = map(mapping_function, my_array)
    # if you want a list
    my_mapped_list = list(mapped_vals)

Я думаю, что это читабельное и понятное решение.

Поскольку вы отметили его как вопрос панд, взгляните на функцию pandas.Series.apply из их документов.Вместо того, чтобы использовать его в качестве карты, вы передаете функцию отображения в качестве аргумента функции apply.

0 голосов
/ 20 февраля 2019

Вы можете сделать это:

arr = np.array([-3-2-1,0,1,2,3,4,5,6])
new_arr = np.zeros(shape = arr.shape, dtype=np.str)

new_arr[(arr>3)] = 'S'
new_arr[((arr>=-3) & (arr<=-1))] = 'F'
new_arr[((arr>=0)&(arr<=3))] = 'M'
new_arr
array(['', 'M', 'M', 'M', 'M', 'S', 'S', 'S'], dtype='<U1')

Значения, которые не соответствуют вашему условию, останутся пустыми строками.

Также вы можете использовать numpy.empty инициализировать пустой массив:

new_arr = np.empty(shape = arr.shape, dtype=np.str)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...