Эффективный способ выбора случайных записей в многомерном массиве numpy - PullRequest
1 голос
/ 30 апреля 2020

Я пытаюсь выработать более эффективный способ сделать это. Вот моя проблема: есть массив (m, n, 2) numpy. Чтобы прояснить ситуацию, я буду называть измерения населением, выборками, а для каждой выборки 0-й столбец - это частота, а 1-й столбец - это амплитуда. Для каждого образца некоторые частоты повторяются, но амплитуды различны. То, что я хочу, - это эффективный способ выбора одной (и только одной) случайной амплитуды для каждой частоты и помещения ее в выходной массив. Пример, чтобы прояснить ситуацию. Предположим, что mth выборка:

1, 2
2, 3
2, 4
3, 5

, а результат должен быть

1, 2
2, 4 (random choice between 3 and 4)
3, 5

Кроме того, частоты в выходном массиве должны быть частотами, присутствующими в другом списке, называемом freq_compare. У меня есть рабочий код, но это занимает некоторое время. Если это помогает, частоты сортируются, но я не знаю заранее, сколько будет дубликатов (если есть), и какие частоты будут дублироваться.

Вот что у меня есть:

def make_dict(sample):
    """Produce a dictionary with the frequencies as keys and amplitudes as values."""
    per_freq = dict()
    freqs = list(set(sample[:,0]))# get list of all frequencies
    for f in freqs:
        per_freq[f] = [line[1] for line in sample if line[0] == f]
    return per_freq

output_random = np.zeros((m, len(freq_compare), 2))
for i in range(m):
    d = make_dict(all_data[i]) #original array
    keys = list(d.keys())
    for j in range(len(freq_compare)):
        if freq_compare[j] in keys:
            amp = np.random.choice(d[freq_compare[j]])
            output_random[i,j,:] = (freq_compare[j], amp)
        else:
            output_random[i,j,:] = (freq_compare[j], 0.0)

Выполнение этого 10 раз заняло около 15 минут для массива формы (3000, 400, 2). Есть ли более эффективный способ? Может быть, построение словаря, когда я перебираю строки?

Большое спасибо

1 Ответ

1 голос
/ 30 апреля 2020

IIU C:

import numpy

m = 3000

freq_compare = np.random.choice(np.arange(0,20), 8, replace=False)
output_random = np.zeros((m, len(freq_compare), 2))
a = np.random.randint(0, 20, (m, 400, 2))

i = 0
for r in a: 

    freqs = np.unique(r[:,0]) 
    d = [[f, np.random.choice(r[r[:,0]==f, 1])] if f in freqs else [f, 0] for f in freq_compare]

    output_random[i] = d
    i+=1

При использовании %timeit на моей локальной машине получается:

710 ms ± 97.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...