Построение одного массива из нескольких. Метод Монте-Карло

Допустим, у нас есть несколько массивов (в моем случае три: a1, a2, a3). У нас также есть еще один массив случайных равномерно распределенных чисел r. Все они одинаковой длины. Мне нужно построить массив a, объединенный из этих трех начальных a1, a2, a3, чтобы, если r[i] удовлетворяет определенному условию 1, мы принимаем a1[i] как a[i], если он удовлетворяет условию 2, мы берем a2[i] и a3[i] с условием 3. три условия являются взаимоисключающими.

Я написал для этого цикл for:

a = empty(len(r))
for i in range(len(r)):
    if r[i] <= p1:
        a[i] = a1[i]
    if p1 < r[i] <= (p1 + p2):
        a[i] = a2[i]
    if r[i] > (p1 + p2):
        a[i] = a3[i]  

Здесь условия 1, 2, 3 выражаются после каждого «if ...». p1 и p2 имеют номера. Это часть моделирования Монте-Карло (массивы a1, a2 и a3 также являются случайными числами с заданным распределением). Это слишком медленно, мне нужно как-то векторизовать его, но я не знаю, как это сделать. Какой способ лучше? Большое спасибо!


person Alexandra Shchukina    schedule 01.10.2013    source источник
comment
Отметьте ответ как «принятый», если он удовлетворительно отвечает на ваш вопрос.   -  person askewchan    schedule 02.10.2013


Ответы (1)


Используйте numpy.select, который позволяет выбирать из нескольких условий:

conds = [r <= p1, r <= (p1 + p2), r > (p1 + p2)]
choices = [a1, a2, a3]
a = np.select(conds, choices)

В вашем случае третьим условием может быть любое условие, которое оценивается как True (например, r == r).

person bogatron    schedule 01.10.2013
comment
Для небольших массивов циклы, вероятно, будут быстрее, но в вопросе говорилось, что метод цикла был слишком медленным, и спрашивался, как векторизовать, что наводит на мысль, что она, вероятно, использует большие массивы. В моих тестах с массивами из 10 000 или более элементов numpy.select был в диапазоне от 20 до 30 раз быстрее, чем явные циклы. - person bogatron; 01.10.2013