Как я могу быстрее составить серию numpy массивов? - PullRequest
0 голосов
/ 12 января 2020

У меня есть xarray DataArray со следующими размерами:

 vals.shape
(210, 587, 1, 1)

содержит одно значение для 210 различных видов за 587 различных дат. Я хотел бы сформировать массив, который является видом х видов для каждого дня, где в данный день каждая строка этой матрицы содержит одинаковые нормализованные (сумма к одному) значения вида для этого дня (т.е. где индекс (i,j) матрица на данную дату содержит значение для вида j в этот день). Мне также нужно, чтобы конечный массив имел дополнительное измерение I и был упорядочен Species x Dates x I x Species

В настоящее время я могу добиться этого, выполнив следующее:

#form a list of species x species matrices:
daily_arrays = [np.array([vals[:, i, 0, 0] for n in range(210)]) for i in 587]

#normalize rows to sum to 1 on each day
daily_arrays = [x / x.sum(axis=1)[:, np.newaxis] for x in daily_arrays]

#stack them up and throw on the `I` dimension
desired_array = np.stack([np.stack(daily_arrays, axis=1)], axis=2)

К сожалению, в настоящее время это занимает более 3 часов (узкое место составляет список daily_arrays). Как я могу express это более эффективно?

Ответы [ 2 ]

1 голос
/ 12 января 2020

Согласно предложению Марка, чтобы избежать python петель для перестановки и больше времени, потраченного на xarray документацию и интерпретатор, следующее решает проблему примерно за 1 секунду, не оставляя xarray:

vals = vals / vals.sum(dim="species")

desired_array = xarray.concat([vals[:, :, :, :] for n in range(210)], "items")
desired_array = desired_array.transpose("items", "dates", "I", "species")

Мне не нужно вставлять измерение, потому что я сохраняю его из исходного массива 210 x 587 x 1 x 1, с которого я начал.

1 голос
/ 12 января 2020

Вы не должны погружаться обратно в циклы python, чтобы изменить порядок массива numpy. Как вы уже обнаружили, это будет медленно на больших наборах данных. Чтобы изменить порядок столбцов, используйте np.transpose

Вы можете go из массива (210, 587, 1, 1) в (587, 210, 1, 1) очень быстро с:

daily_arrays = np.transpose(vals, (1, 0, 2, 3))

Это даст вам строку для каждого дня и столбец для каждого вида.

С этим вы можете нормализовать в numpy также без python l oop с использованием:

daily_arrays/daily_arrays(axis = 1, keepdims=1)

Я не совсем уверен, почему ваши данные являются 4-мерными (почему бы просто не использовать матрицу 210 x 587) - но я предполагаю, что у вас есть причина для дополнительные однозначные размеры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...