#python #numpy-ndarray
#питон #numpy-ndarray
Вопрос:
В качестве минимального рабочего примера у меня есть file.txt содержащий список номеров:
1.1
2.1
3.1
4.1
5.1
6.1
7.1
8.1
который на самом деле должен быть представлен с индексами, что делает его 3D-массивом
0 0 1.1
1 0 2.1
0 1 3.1
1 1 4.1
0 2 5.1
1 2 6.1
0 3 7.1
1 3 8.1
Я хочу импортировать 3D-массив в python и использую bash для генерации индексов, а затем вставляю индекс в file.txt перед импортом результирующего full.txt в python с использованием pandas:
for ((y=0;y<=3;y )); do
for ((x=0;x<=1;x )); do
echo -e "$xt$y"
done
done
done > index.txt
paste index.txt file.txt> full.txt
Написание index.txt был медленным в моем реальном коде, который имеет x до 9000 и y до 5000. Есть ли способ сгенерировать индексы в первые 2 столбца 2D-массива python numpy, чтобы мне нужно было только импортировать данные из file.txt как насчет третьей колонки?
Комментарии:
1. Я не могу понять, что такое входные данные и что должен делать код
2. «у которого x до 9000 и y до 5000», значит, вам нужно сгенерировать ~ 45 миллионов строк? Что для вас означает «медленный»? Кроме того, как это 3D-массив? Где 3-е измерение?
3. В настоящее время код bash использует около 5 минут для записи index.txt системы рядов длиной 10 метров. Я думаю, что это ввод-вывод, который ограничивает скорость, поэтому, если бы я мог просто создать массив с индексами, это было бы намного быстрее.
Ответ №1:
Я бы рекомендовал использовать pandas
для загрузки данных и управления столбцами разных типов. Мы можем сгенерировать индексы np.indices
с желаемыми размерами и reshape
в соответствии с вашим форматом. Затем объедините ‘file.txt «.
Создание индекса для (9000,5000)
занимает около 950ms
экземпляра colab.
import numpy as np
import pandas as pd
x,y = 2,4 # dimensions, also works with 9000,5000 but assumes 'file.txt' has the correct size
pd.concat([
pd.DataFrame(np.indices((x,y)).ravel('F').reshape(-1,2), columns=['ind1','ind2']),
pd.read_csv('file.txt', header=None, names=['Value'])
], axis=1)
Вон:
ind1 ind2 Value
0 0 0 1.1
1 1 0 2.1
2 0 1 3.1
3 1 1 4.1
4 0 2 5.1
5 1 2 6.1
6 0 3 7.1
7 1 3 8.1
Как это работает
Сначала создайте индексы для желаемых размеров с помощью np.indices
np.indices((2,4))
Вон:
array([[[0, 0, 0, 0],
[1, 1, 1, 1]],
[[0, 1, 2, 3],
[0, 1, 2, 3]]])
Что дает нам правильные индексы, но в неправильном порядке.
С np.ravel('F')
помощью мы можем указать flatten
массив в столбцах первого порядка
np.indices((2,4)).ravel('F')
Вон:
array([0, 0, 1, 0, 0, 1, 1, 1, 0, 2, 1, 2, 0, 3, 1, 3])
Чтобы получить нужные столбцы reshape
в виде 2D — массива с формой (8,2)
. С (-1,2)
помощью первого измерения делается вывод.
np.indices((2,4)).ravel('F').reshape(-1,2)
Вон:
array([[0, 0],
[1, 0],
[0, 1],
[1, 1],
[0, 2],
[1, 2],
[0, 3],
[1, 3]])
Затем преобразуйте в a dataframe
со столбцами ind1
и ind2
.
Работа с большим количеством измерений
pd.DataFrame(np.indices((2,4,3)).ravel('F').reshape(-1,3)).add_prefix('ind')
Вон:
ind0 ind1 ind2
0 0 0 0
1 1 0 0
2 0 1 0
3 1 1 0
4 0 2 0
5 1 2 0
6 0 3 0
7 1 3 0
8 0 0 1
9 1 0 1
10 0 1 1
11 1 1 1
12 0 2 1
13 1 2 1
14 0 3 1
15 1 3 1
16 0 0 2
17 1 0 2
18 0 1 2
19 1 1 2
20 0 2 2
21 1 2 2
22 0 3 2
23 1 3 2
Комментарии:
1. Можете ли вы объяснить строку pd.DataFrame(np.indexes((x,y)).ravel(‘F’).reshape(-1,2), columns=[‘ind1′,’ind2’])? Меня немного смущает равель (‘F’).изменить форму (-1,2)
2. Очень хороший ответ! Def. превосходит мой по простоте. Однако я бы оценил более глубокое объяснение индексации для будущих читателей
3. Добавлено краткое объяснение того, как создается индекс.
4. Это тот же синтаксис. Я добавил пример.
5. Мне удалось разобраться с синтаксисом и только что удалил вопрос. Большое спасибо за обновленный ответ!
Ответ №2:
Вот краткий пример того, как создать 3D-массив из 1D-массива. В качестве фиктивного у меня есть случайные числа. Затем он создает кортежи из x, y, value .
Для 45 миллионов строк требуется около минуты
from random import randrange
x = 5000
y = 9000
numbers = [randrange(100000,999999) for i in range(x*y)]
array = [(a,b, numbers[b*(x-1) a]) for a in range(x) for b in range(y)]
Вывод
pd.DataFrame(array)
Out[23]:
0 1 2
0 0 0 878704
1 0 1 524573
2 0 2 943657
3 0 3 496507
4 0 4 802714```
Комментарии:
1. На самом деле я также застрял в том, как импортировать значения file.txt как столбец 2 массива. Есть идеи, как это сделать?
2. @Jacek Что ты имеешь в виду? Значения из file.txt нужно быть вчитанным в
numbers
3. Ах, хорошо, я только что понял, как массив чисел считывается в «массив». Позвольте мне попробовать
4. Помогает ли это, или вам чего-то не хватает?
5. Это работает. Но я изучаю ответ Майкла Щесны, который я изначально имел в виду. Еще большое спасибо!
Ответ №3:
Если вы хотите придерживаться своего bash, вы можете избежать двух циклов:
Код:
for ((y=0;y<=3;y )); do
echo -e "0t$yn1t$y"
done
Вывод:
0 0
1 0
0 1
1 1
0 2
1 2
0 3
1 3
выше в python:
Код:
for y in range(4):
print(f'0t{y}n1t{y}')
Вывод:
0 0
1 0
0 1
1 1
0 2
1 2
0 3
1 3