Выбор случайным образом из двух массивов на основе условий в Python

1

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

a = [0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,0,1]
b = [0,1,1,0,1,0,0,1,1,0,0,1,1,0,1,0,0]

Теперь я хочу выбрать элементы из этих двух массивов в последовательности, заданной так, чтобы они формировали новый массив той же длины, что и a & b, путем случайного выбора значений между a & b в соотношении a: b = 4.68, то есть для Каждое 1 значение, выбранное из a, должно быть 4.68 значений, выбранных из b в результирующем массиве.

Таким образом, результирующий массив может выглядеть примерно так:

res = [0,1,1,0,1, 1(from a) ,0(from a),1,1,0,0,1,1,0, 0(from a),0,0]

массив res имеет: первые 5 значений от b, 6 и 7 от a, 8-14 от b, 15 от a, 16-17 от b

Общее соотношение значений от a: b в данном примере массива res составляет: b 4,67 (от a = 3, от b = 14)

Таким образом, между двумя массивами значения должны выбираться случайным образом, однако последовательность должна поддерживаться, т.е. Не может принимать 7-е значение из одного массива и 3-е значение из другого. Если значение, которое нужно заполнить в результирующем массиве, равно 3, то выбор между 3-й элемент обоих входных массивов в произвольном порядке. Также необходимо поддерживать общее соотношение.

Не могли бы вы помочь мне в разработке эффективного Pythonic способа достижения этого результирующего решения? Решение не обязательно должно быть согласовано с каждым прогоном по значениям

  • 0
    Вы можете использовать NumPy?
  • 1
    Должно ли соотношение быть максимально точным или просто вероятным?
Показать ещё 4 комментария
Теги:
arrays
python-2.7

2 ответа

1
Лучший ответ

Заимствуя расчет a_count из ответа Barmar (потому что он, кажется, работает, и я не могу потрудиться заново его изобрести), это решение сохраняет порядок значений, выбранных из a и b:

from future_builtins import zip  # Only on Python 2, to avoid temporary list of tuples
import random

# int() unnecessary on Python 3
a_count = int(round(1/(1 + 4.68) * len(a)))

# Use range on Python 3, xrange on Python 2, to avoid making actual list
a_indices = frozenset(random.sample(xrange(len(a)), a_count))

res = [aval if i in a_indices else bval for i, (aval, bval) in enumerate(zip(a, b))]

Основная идея здесь заключается в том, что вы определяете, сколько a значения вам нужно, получить уникальный образец из возможных индексов такого размера, а затем итерация и a b параллельно, сохраняя a значение для выбранных показателей, а b значения для всех другие.

Если вам не нравится сложность понимания list, вы можете использовать другой подход, копируя b, затем заполняя значения a одно за другим:

res = b[:]  # Copy b in its entirety

# Replace selected indices with a values
# No need to convert to frozenset for efficiency here, and it clean
# enough to just iterate the sample directly without storing it
for i in random.sample(xrange(len(a)), a_count):
    res[i] = a[i]
  • 0
    Получение этого TypeError: не может умножить последовательность на не-int типа 'float'
  • 0
    @raul: Да, я забыл, что это было для Python 2. Просто нужно преобразование int (уже отредактировано в), потому что round в Python 2 всегда возвращает float (в Python 3 он возвращает float только при передаче второго аргумента, а int для один аргумент). Примечание: Python 2 достигает конца срока службы менее чем за год . Новый код должен действительно предназначаться для Python 3.
Показать ещё 1 комментарий
1

Я считаю, что это должно работать. Вы указываете, сколько вы хотите от (вы можете просто использовать свое соотношение, чтобы выяснить это число), вы случайным образом генерируете "маску" чисел и выбираете из или, основываясь на срезе (обратите внимание, что вы только сортируете, чтобы выяснить, отсечка, но вы используете несортированную маску позже)

import numpy as np

a = [0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,0,1]
b = [0,1,1,0,1,0,0,1,1,0,0,1,1,0,1,0,0]

mask = np.random.random(len(a))
from_a = 3
cutoff = np.sort(mask)[from_a]

res = []
for i in range(len(a)):
    if (mask[i]>=cutoff):
        res.append(a[i])
    else:
        res.append(b[i])

Ещё вопросы

Сообщество Overcoder
Наверх
Меню