Добавить массив в цикл for

У меня есть фрейм данных с 1000 строк и 1000 столбцов. Я пытаюсь создать массив numpy из этого фрейма данных, используя цикл for, я использую цикл for для случайного выбора 5 столбцов за цикл. Мне нужно добавить или объединить каждый массив (1000 строк и 5 столбцов), который я генерирую за цикл. Однако видно, что невозможно создать массив numpy без указания сначала размеров.

Я пробовал следующий код:

import numpy as np
import pandas as pd


df = pd.DataFrame(np.random.choice([0.0, 0.05], size=(1000,1000)))

l =  np.array([])

for i in range(0,100):
 rand_cols = np.random.permutation(df.columns)[0:5]
 df2 = df[rand_cols].copy()
 l = np.append(l, df2, axis=0)

Однако я получаю следующую ошибку:

ValueError: all the input arrays must have same number of 
dimensions

Этот код резюмирует то, что я делаю, однако, согласно этому примеру, результат, который мне нужен, — это массив из 1000 строк и 500 столбцов, который создается путем конкатенации каждого из массивов, которые я генерирую с каждым циклом for.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
8 373
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

IIUC

l=[]

for i in range(0,100):
 rand_cols = np.random.permutation(df.columns)[0:5]
 df2 = df[rand_cols].copy()
 l.append(df2.values)


a=np.concatenate(l,1)
a.shape
(1000, 500)
Ответ принят как подходящий

Добавление списка всегда лучше, чем np.append. Это быстрее и проще в использовании.

Но давайте посмотрим на ваш код более подробно:

In [128]: df = pd.DataFrame(np.random.choice([0.0, 0.05], size=(1000,1000)))    
In [129]: l = np.array([])                                                      
In [130]: rand_cols = np.random.permutation(df.columns)[0:5]                    
In [131]: rand_cols                                                             
Out[131]: array([190, 106, 618, 557, 514])
In [132]: df2 = df[rand_cols].copy()                                            
In [133]: df2.shape                                                             
Out[133]: (1000, 5)
In [134]: l1 = np.append(l, df2, axis=0)                                        
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-134-64d82acc3963> in <module>
----> 1 l1 = np.append(l, df2, axis=0)

/usr/local/lib/python3.6/dist-packages/numpy/lib/function_base.py in append(arr, values, axis)
   4692         values = ravel(values)
   4693         axis = arr.ndim-1
-> 4694     return concatenate((arr, values), axis=axis)
   4695 
   4696 

ValueError: all the input arrays must have same number of dimensions

Поскольку вы указали ось, все, что делает np.append, это:

np.concatenate([l, df2], axis=0)

l это (0,) форма, df2 это (1000,5). 1д и 2д, отсюда и претензии к габаритам.

Начиная с 2d массива l работает:

In [144]: l = np.zeros((0,5))                                                   
In [145]: np.concatenate([l, df2], axis=0).shape                                
Out[145]: (1000, 5)
In [146]: np.concatenate([df2, df2], axis=0).shape                              
Out[146]: (2000, 5)

Я думаю, что np.append следует устареть. Мы видим слишком много ошибок SO. Как показывает ваш случай, сложно создать правильный исходный массив. np.array([]) работает только при построении массива 1d. Плюс повторные конкатенации медленные, каждый раз создавая совершенно новый массив.

Предложенное решение

Причина, по которой вы получаете эту ошибку, заключается в том, что вы пытаетесь добавить матрицу df2 формы (1000, 5) к матрице l формы (0,) (только одно измерение). Проблема в том, что с numpy две объединенные матрицы должны совпадать по размерам, И все размеры, кроме того, к которому вы добавляете, должны быть выровнены, т. е. вы должны были инициализировать l формой (0, 5).

Вот рабочая версия кода:

import numpy as np
import pandas as pd


df = pd.DataFrame(np.random.choice([0.0, 0.05], size=(1000,1000)))

l =  np.empty(shape=(0, 5))

for _ in range(0,100):
    rand_cols = np.random.permutation(df.columns)[0:5]
    df2 = df[rand_cols]
    l = np.append(l, df2, axis=0)

Предлагаемое улучшение

Теперь рекомендуется избегать добавления матриц внутри цикла, поскольку это неэффективно с точки зрения вычислений (на каждой итерации необходимо создавать новый массив numpy, что требует времени). Вам лучше добавить результат итерации цикла в стандартный список Python и дождаться окончания выполнения цикла, чтобы сложить все результаты вместе.

Вот код:

import numpy as np
import pandas as pd


df = pd.DataFrame(np.random.choice([0.0, 0.05], size=(1000,1000)))

df_list = []

for _ in range(0,100):
    rand_cols = np.random.permutation(df.columns)[0:5]
    df2 = df[rand_cols]
    df_list += [df2]
l = np.vstack(df_list)

Здесь я использую numpy.vstack для конкатенации вдоль оси строки. Другие функции numpy с соответствующими параметрами дадут вам тот же результат. Обратите внимание, что нет необходимости преобразовывать кадры данных pandas в массивы numpy.

На моем компьютере это небольшое улучшение сократило время вычислений со 164 мс до 107 мс (значения взяты из быстрого выполнения каждой версии). Конечно, это не так важно здесь, но я думаю, что это полезно знать :)

Другие вопросы по теме