Мой вопрос заключается в том, как эффективно расширить массив, многократно копируя себя. Я пытаюсь расширить выборки опроса до полного набора данных, копируя каждую выборку N раз. N - это фактор влияния, который подписан на выборку. Поэтому я написал два цикла для выполнения этой задачи (скрипт вставлен ниже). Это работает, но медленно. Мой размер выборки составляет 20 000, и попробуйте расширить его до 3 миллионов в полном размере. Есть ли какая-нибудь функция, которую я могу попробовать? Спасибо за помощь!

---- мой сценарий ----

lines = np.asarray(person.read().split('\n'))
df_array = np.asarray(lines[0].split(' '))
for j in range(1,len(lines)-1):
    subarray = np.asarray(lines[j].split(' '))
    factor = int(round(float(subarray[-1]),0))
    for i in range(1,factor):
        df_array = np.vstack((df_array, subarray))
print len(df_array)
5
Angela Y 19 Дек 2015 в 02:52

3 ответа

Лучший ответ

Сначала вы можете попытаться загрузить все данные вместе с numpy.loadtxt.

Затем, чтобы повторить в соответствии с последним столбцом, используйте numpy.repeat:

>>> data = np.array([[1, 2, 3],
...                  [4, 5, 6]])
>>> np.repeat(data, data[:,-1], axis=0)
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3],
       [4, 5, 6],
       [4, 5, 6],
       [4, 5, 6],
       [4, 5, 6],
       [4, 5, 6],
       [4, 5, 6]])

Наконец, если вам нужно округлить data[:,-1], замените его на np.round(data[:,-1]).astype(int).

2
eph 19 Дек 2015 в 01:16

Повторное накопление массивов с кучей не очень эффективно, потому что они не оптимизированы для такого динамического роста. Каждый раз, когда вы vstack, он выделяет новый объем памяти для размера ваших данных в этот момент.

Используйте списки, а затем создайте свой массив в конце, возможно, с генератором, подобным этому:

def upsample(stream):
    for line in stream:
        rec = line.strip().split()
        factor = int(round(float(rec[-1]),0))
        for i in xrange(factor):
            yield rec

df_array = np.array(list(upsample(person)))
1
fivetentaylor 19 Дек 2015 в 00:15

Концепция, которую вы ищете, называется broadcasting. Это позволяет вам заполнять массив n dimensional содержимым массива n-1 dimensional.

Глядя на пример кода, вы вызываете np.vstack() в цикле. Вещание устранит петлю.

Например, если у вас есть одномерный массив n элементов,

>>> n = 5
>>> df_array = np.arange(n)
>>> df_array
array([0, 1, 2, 3, 4])

Затем вы можете создать новый массив n x 10:

>>> bigger_array = np.empty([10,n])
>>> bigger_array[:] = df_array
>>> bigger_array
array([[ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.]])

Итак, одной строкой кода вы можете заполнить ее содержимым меньшего массива.

large_array [:] = df_array

NB . Избегайте использования списков Python. Они намного, намного медленнее, чем Numpy ndarray.

1
timbo 19 Дек 2015 в 00:30