создание столбцов индекса с помощью python

#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