На прошлой неделе я написал в блоге о Pandas 12 Pandas Methods To Master: A Complete Roadmap To Be A Data Scientist… и получил просто ошеломляющий ответ… никогда не думал, что смогу помочь такому количеству людей.

Итак, вот мой третий блог…

Итак, мы закончили с Python и Pandas, что дальше?

Очевидно, это будет NumPy. Но..

Почему NumPy?

Итак, с чем мы имеем дело в науке о данных?

Данные, верно?

Да, и как мы храним данные?

Множество? Список? Словарь?

Верно. Теперь представьте, что мы имеем дело с тоннами и тоннами данных, и данные, которые мы храним, очень медленные. Какой будет опыт?

Ужасный.

Абсолютно, и именно поэтому мы используем NumPy. В науке о данных NumPy является основным пакетом для выполнения высокоуровневых математических вычислений над многомерными массивами.

Поэтому мы храним данные в массивах NumPy и используем NumPy для выполнения этих вычислений.

Но почему NumPy быстрее?

Это связано с тем, что пакет NumPy интегрируется с C/C++, и эти языки требуют гораздо меньше времени для выполнения, чем обычный массив Python, а также NumPy использует гораздо меньше памяти для хранения данных. Таким образом, огромная разница во времени, а значит, более эффективный.

Теперь, когда понятно, почему NumPy, давайте импортируем numpy как np в вашу жизнь.

Сегодня мы поговорим о 12 методах NumPy для начинающих.

«Начинающие», потому что использование NumPy настолько велико, что мне пришлось написать еще один блог, чтобы осветить продвинутую часть NumPy. Мы обсудим их позже, когда перейдем к реальным вещам машинного обучения. На данный момент, я думаю, этого будет достаточно.

Создание собственного массива:

В NumPy есть много способов создать свой собственный массив для экспериментов.

# creating an 1D array 
a = np.array([1, 2, 3])
print(a)
-> [1 2 3]

Этот метод .array() используется для создания массива любого измерения, которое вы хотите. Теперь в NumPy измерения называются осями. Таким образом, массив 1D будет иметь 1 ось, массив 2D будет иметь 2 оси и так далее.

# creating a 2D array
a = np.array([[1, 2, 3], [4, 5, 6]])
print(a)
-> [[1 2 3], [4 5 6]]

Таким образом, мы можем создавать n-мерные массивы в NumPy.

# creating an array of zeros
a = np.zeros(2)
print(a)
-> [0. 0.]

Вместо того, чтобы помещать какие-либо целые числа, мы можем просто создать массив нулей с помощью этого метода .zeros.

# creating an array of ones
a = np.ones(2)
print(a)
-> [1. 1.]

Также мы можем использовать массив только из 1 с помощью .ones().

# creating an arranged array
a = np.arange(4)
print(a)
-> [0 1 2 3]

Этот метод .arage() используется для создания массива путем предоставления диапазона элементов. У этого метода есть 4 входа: start, stop, step и dtype.

# creating an arranged array
a = np.arange(2, 9, 2, 'int')
b = np.arange(2, 9, 2, 'float')
print(a)
print(b)
-> [2 4 6 8]
-> [2. 4. 6. 8.]

Таким образом, мы можем использовать .arange() для создания массива. Однако в NumPy есть еще один метод, который работает почти так же, как .arange(), и это .linspace().

# creating an array using linspace
a = np.linspace(0, 10, num=5)
print(a)
-> [ 0.   2.5  5.   7.5 10. ]

Здесь, в .linspace(), мы также можем указать несколько входных данных, таких как .arange().

Но как новичок, вам должно быть ясно, в чем разница между этим .arange() и .linspace()… поскольку они работают почти одинаково, тогда зачем хранить оба ?

np.arange() возвращает значения в пределах диапазона, между значениями которого есть пробел.

a = np.arange(0, 10, 5)
print(a)
-> [0 5]

В то время как np.linspace() возвращает набор образцов в пределах заданного интервала.

a = np.linspace(0, 10, 5)
print(a)
-> [ 0.   2.5  5.   7.5 10. ]

Мы видим, что linspace возвращает 5 равноотстоящих значений в пределах интервала, а arange возвращает 2 значения с шагом 5 в диапазоне от 0 до 10.

.ndim , .size , .shape:

Эти методы мы используем, когда у нас есть массив, в котором мы хотим узнать, какова размерность этого массива, общее количество элементов и его форма.

# using .ndim , .size , .shape
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9])
print(a)
print(a.ndim)
print(a.size)
print(a.shape)
-> [[1 2 3]
   [4 5 6]
   [7 8 9]]  # 3D array
-> 2
-> 9
-> (3, 3)

.ndim используется для получения размера массива, .size используется для определения общего количества элементов в массиве, а .shape используется для получения форма массива (здесь это массив 3x3, что означает 3 строки и 3 столбца).

изменить форму():

Иногда нам нужно изменить форму массива, с помощью .reshape() мы можем это сделать.

# reshaping an array
a = np.arange(6)
print(a)
-> [0 1 2 3 4 5]
b = a.reshape(3, 2)
print(b)
-> [[0 1]
   [2 3]
   [4 5]]

Таким образом, мы можем использовать метод .reshape() для изменения формы массива.

Здесь следует помнить одну вещь: когда вы используете метод изменения формы, массив, который вы хотите создать, должен иметь то же количество элементов, что и исходный массив. Если вы начинаете с массива из 12 элементов, вам необходимо убедиться, что ваш новый массив также имеет в общей сложности 12 элементов.

сортировка():

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

# sorting an array in ascending order
a = np.array([2, 1, 5, 3, 7, 4, 6, 8])

print(np.sort(a))
-> [1 2 3 4 5 6 7 8]

Вот как мы сортируем массив в порядке возрастания. Мы также можем отсортировать массив в порядке убывания.

# sorting an array in descending order
a = np.array([2, 1, 5, 3, 7, 4, 6, 8])

asc = np.sort(a)
print(asc)
desc = np.flip(asc)
print(desc)
-> [1 2 3 4 5 6 7 8]
-> [8 7 6 5 4 3 2 1]

Мы можем использовать .flip(), чтобы изменить порядок массива.

Подробнее о сортировке здесь.

объединить():

Иногда нам нужно добавить несколько массивов для выполнения некоторых вычислений, поэтому у нас есть concatenate()в NumPy.

# concatenating two arrays
a = np.array([1, 2, 3, 4])
b = np.array([5, 6, 7, 8])
print(np.concatenate((a, b)))
-> [1 2 3 4 5 6 7 8]
x = np.array([[1, 2], [3, 4]])
y = np.array([[5, 6]])
print(np.concatenate((x, y), axis=0))
-> [[1 2]
   [3 4]
   [5 6]]

Индексирование и Нарезка:

Это еще один важный момент, почему мы используем массивы NumPy вместо списков Python. В списке Python мы не можем выполнять операции со всеми элементами двух списков напрямую. Например, мы не можем умножить два списка напрямую, нам придется делать это поэлементно. Именно здесь вступает в игру роль NumPy.

# using index values to get some elements from the array
a = np.array([1, 2, 3, 4, 5, 6, 7, 8])
arr = a[np.array([1, 3, -3])]
print(arr)
-> [2 4 6]

Дело в том, что в любом массиве каждый элемент имеет свое значение индекса, и он начинается с 0. Таким образом, первый элемент в массиве имеет 0-й индекс, второй элемент имеет 1-й индекс и так далее.

Мы можем сделать это и в обратном порядке, но здесь оно начинается с -1. Таким образом, для последнего элемента (8) индекс равен -1, второй последний (7) имеет -2 и так далее.

Таким образом, здесь, в индексе, мы передали 3 входа, дав нам элемент 1-го индекса, 3-го индекса и -3-го индекса... и на основе этого мы получили наш вывод.

# using basic slicing
a = np.arange(20)
print(a)
-> [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19]
print(a[10:])  # first
-> [10 11 12 13 14 15 16 17 18 19]
print(a[-8:18:2])  # second
-> [12 14 16]

В случае нарезки мы не передаем номер индекса (хотя и не в каждом случае), здесь мы передаем фактический элемент, с которого мы хотим начать. Таким образом, при нарезке мы можем передать 3 входа: Start, End, Steps. Что ж, в случае End это на самом деле (End-1). Таким образом, он всегда будет останавливаться за 1 шаг до конца.

В приведенном выше массиве (a) мы пытались получить (a[10:]) в первом примере. Здесь, поскольку мы оставили вторую позицию пустой, мы получаем полный массив, начиная с 10.
Тогда как во втором примере мы дали ( a[-8:18:1] ). Здесь мы дали -8 в качестве начального, что означает, что мы дали -8-й индекс (вместо фактического числа), который здесь равен 12. Затем мы дали 18 в качестве конечного элемента, таким образом, мы получили 17 на выходе. Наконец, мы упомянули 2 в качестве наших шагов (по умолчанию steps = 1). Так как мы дали здесь 2, мы будем получать каждый второй элемент от элемента 12 до элемента 18.

Подробнее об индексировании и нарезке здесь.

Создание массива из существующего массива:

Вы можете легко создать новый массив из существующего массива.

# creating a new array from an existing one
a = np.array([1, 2, 3, 4, 5, 6, 7, 8])
arr = a[2:6]
print(arr)
-> [3 4 5 6]

Здесь мы захватили часть вашего массива от позиции индекса 2 до позиции индекса 6.

Вы также можете сложить два существующих массива вертикально и горизонтально.

# creating a new array from an existing one
a1 = np.array([[1, 1], [2, 2]])
a2 = np.array([[3, 3], [4, 4]])
print(np.vstack((a1, a2)))  # vertically
print(np.hstack((a1, a2)))  # horizontally
-> [[1 1]
    [2 2]
    [3 3]
    [4 4]]
-> [[1 1 3 3]
    [2 2 4 4]]

Таким образом, мы можем сложить два или более таких массива, используя .vstack() для вертикального стека и .hstack() для горизонтального стека.

где():

В NumPy мы можем искать в массиве определенное значение, а взамен мы получаем индекс этого конкретного элемента, который мы искали.

# searching through an array
arr = np.array([1, 2, 3, 4, 5, 4, 4])
x = np.where(arr == 4)
print(x)
-> (array([3, 5, 6]),)

Таким образом, мы можем использовать метод .where() для поиска любого элемента/элементов в массиве.

# searching even numbers through an array
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
x = np.where(arr%2 == 0)
print(x)
-> (array([1, 3, 5, 7]),)

уникальный():

Если мы хотим найти все уникальные значения из массива, мы можем использовать .unique().

# searching unique elements from an array
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [1, 2, 3, 4]])
unique_values = np.unique(arr)
print(unique_values)
-> [ 1  2  3  4  5  6  7  8  9 10 11 12]

Мы также можем получить уникальные строки или столбцы, используя аргумент axis.

axis=0 для уникальных строк и axis=1 для уникальных столбцов.

# searching unique elements from an array
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [1, 2, 3, 4]])
unique_rows = np.unique(arr, axis=0)
print(unique_values)
-> [[ 1  2  3  4]
    [ 5  6  7  8]
    [ 9 10 11 12]]

транспонировать():

Любой массив, будь то одномерный, двухмерный или любой многомерный массив, можно назвать матрицей. И много раз нам нужно транспонировать матрицу. Именно поэтому мы можем выбрать метод .transpose().

# transposing an array
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [1, 2, 3, 4]])
print(arr.transpose())
-> [[ 1  5  9  1]
    [ 2  6 10  2]
    [ 3  7 11  3]
    [ 4  8 12  4]]
print(arr.T)
-> [[ 1  5  9  1]
    [ 2  6 10  2]
    [ 3  7 11  3]
    [ 4  8 12  4]]

Таким образом, чтобы транспонировать матрицу, мы можем использовать либо .transpose(), либо .T. Оба работают одинаково.

Основные математические функции:

В массивах NumPy мы можем выполнять некоторые основные математические функции, такие как плюс, минус, умножение, деление.

# adding two arrays
arr1 = np.array([1, 2])
arr2 = np.ones(2, dtype=int)
print(arr1 + arr2)
-> [2 3]
# subtracting two arrays
print(arr1 - arr2)
-> [0 1]
# multiplication of two arrays
print(arr1 * arr2)
-> [1 2]
# division of two arrays
print(arr1 / arr2)
-> [1. 2.]

Наиболее полезные операции с массивами:

Это одни из наиболее часто используемых методов в NumPy.

# finding minimum
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
print(arr.min())
-> 1
# finding maximum
print(arr.max())
-> 8
# finding mean
print(arr.mean())
-> 4.5
# finding variance
print(arr.var())
-> 5.25
# finding standard deviation
print(arr.std())
-> 2.29128784747792
# sum of all the elements within an array
print(arr.sum())
-> 36
# multiplication of all the elements within an array
print(arr.prod())
-> 40320

Еще раз, использование NumPy в науке о данных ни на что не похоже. Поэтому, пожалуйста, учитесь и играйте с этой библиотекой столько, сколько сможете. Для справки вы можете посмотреть здесь.

Надеюсь, это помогло. Я собираюсь рассказать больше о своем путешествии, которое будет полностью удобным для новичков. Посмотрите мои другие блоги на Medium или мы можем связаться на LinkedIn.