# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: 'Python 3.8.10 64-bit (''.venv'': poetry)'
#     name: python3
# ---

# + [markdown] id="-JUOp2KEdHTn"
# # Numpy (Часть 1)
#
# -

# > 🚀 В этой практике нам понадобятся: `numpy==1.21.2` 
#
# > 🚀 Установить вы их можете с помощью команды: `!pip install numpy==1.21.2` 
#

# ## Содержание
#
# * [Создание массивов](#Создание-массивов)
# * [Хитрая индексация](#Хитрая-индексация)
#   * [Задание - подумаем](#Задание---подумаем)
#   * [Задание - учимся обращать](#Задание---учимся-обращать)
#   * [Задание - подмассив](#Задание---подмассив)
# * [Хитрая индексация в матрицах](#Хитрая-индексация-в-матрицах)
#   * [Задание - еще больше срезаем](#Задание---еще-больше-срезаем)
#   * [Задание - кручу-верчу - запутать хочу](#Задание---кручу-верчу---запутать-хочу)
# * [Типы данных в массивах](#Типы-данных-в-массивах)
#

# + [markdown] id="oTtiG3HMz-Rt"
# Numpy - это библиотека для математических вычислений. Написана на языке С, поэтому считается наиболее предпочтительным вариантом при работе с многомерными массивами из-за производительности.
#
# [Официальный сайт](https://numpy.org/doc/stable/) последней стабильной версии.
#
# Начало работы с `numpy` заключается в подключении модуля. При этом в практике применения есть уже общепринятое сокращение для него под названием `np`:

# + id="2HARN7afZ1Fk" _cell_id="eRqhqWJYAXeRpzds"
import numpy as np

# + [markdown] id="81-wHdEbg-qI"
# > Если вы ранее работали с MATLAB, обратите внимание, как некоторые подходы и функции схожи.

# + [markdown] id="woHgRbgPZ99s"
# ## Создание массивов

# + [markdown] id="DVVfQ6DwaBUH"
# Для того, чтобы начать работать с `numpy`, мы должны научиться создавать объекты `ndarray`, которые по сути являются N-мерными массивами.

# + id="kQqPek1xZ2y7" _cell_id="3mOjAqnJcXKV5NDk"
# Самый просто способ создать массив numpy - взять уже существующий list и передать в функцию np.array()
arr_1d = np.array([1, 2, 3])

# + colab={"base_uri": "https://localhost:8080/", "height": 120} executionInfo={"elapsed": 15150, "status": "ok", "timestamp": 1598902935962, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="7thycVOKbCJ7" outputId="c85066c9-3e5b-4d58-ee33-7de5dc3cbf4d" _cell_id="0MEgr0VrZz1FB6D0"
# Теперь проверим 
#   - тип объекта c помощью функции type()
#   - размерность с помощью аттрибута .shape
#   - доступ по индексам, как у обычного list

# Для отладки можно выводить небольшие массивы прямо через print()

print(arr_1d)
print(type(arr_1d))
print(arr_1d.shape)
print(arr_1d[0])
print(arr_1d[2])
print(arr_1d[-1])

# + [markdown] id="90qAyGF8bLLs"
# > Обратите внимание, индекс с отрицательным значением означает индексацию с конца. Это возможность языка Python. В данном случае индекс -1 ~ 2, так как 2 - последний индекс в массиве из трёх элементов. Аналогично, если хотите взять второй элемент с конца, то можете использовать индекс -2 и т.д.

# + [markdown] id="GlDZi0V_bijd"
# Как видите, объект имеет тип `np.ndarray`, таким образом описываются все массивы при работе с numpy. Размерность представляет собой кортеж с одним элементом (создали 1D массив ~ массив первого ранга в терминах numpy).

# + id="WfMA2hmgcPFH" _cell_id="6qgOFb8cHqbIiU4n"
# Теперь создадим двумерный массив с помощью тех же list
arr_2d = np.array([[1, 2, 3], [4, 5, 6]])

# + colab={"base_uri": "https://localhost:8080/", "height": 137} executionInfo={"elapsed": 15020, "status": "ok", "timestamp": 1598902935969, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="ljaLlNS2cdvd" outputId="99ffe98e-8fee-41be-9cf5-c333eb786dd6" _cell_id="jKs4DjKg0FZmaqme"
# Проверим также тип, размерность и доступ по индексам

print(arr_2d)
print(type(arr_2d))
print(arr_2d.shape)
print(arr_2d[0, 0])
print(arr_2d[1, 2])
print(arr_2d[1, 0])

# + [markdown] id="wQKPgHh7cOlh"
# Теперь видно, что в кортеже размерности стало два элемента, при этом тип объекта никак не поменялся.
#
# Индексация в 2D массиве делается уже посредством двух индексов:
# - первый индекс - номер ряда (строки);
# - второй индекс - номер колонки (столбца).
#
# > В 1D массивах вообще никаких вопросов не возникает, в 2D (ряд, колонка), если разворачивать до 3D массивов, то можно интерпретировать как (ряд, колонка, глубина). Дальнейшие размерности уже сложнее в визуальной интерпретации, поэтому вместо названий для каждой размерности идет просто индексация.

# + [markdown] id="zeUwMz9aem4U"
# Помимо способов создания массивов из уже существующих представлений в виде `list`, можно также создавать массивы по-другому. Рассмотрим некоторые из них:
#

# + colab={"base_uri": "https://localhost:8080/", "height": 102} executionInfo={"elapsed": 14908, "status": "ok", "timestamp": 1598902935983, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="W8EnLNXlf6HW" outputId="a8213954-9261-48e8-b049-1c2435edc251" _cell_id="emYiBpuF9MyqQW8X"
# Создание массива фиксированного размера
np.ndarray((5, 3))

# + [markdown] id="IAHEQ5N2gUP_"
# В представленном способе мы напрямую вызываем конструктор и передаем ему размерность. Какими числами будет заполнен массив - никто не знает. Вероятнее всего, это будут нули, но для уверенности лучше самостоятельно заполнить такой массив данными.

# + colab={"base_uri": "https://localhost:8080/", "height": 51} executionInfo={"elapsed": 14829, "status": "ok", "timestamp": 1598902935992, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="U4fnZoDMgJc6" outputId="2917284c-b8a9-45a9-8d9c-f48cde9905fb" _cell_id="3sYrTHQPVXXgkzwg"
# Явное создание массива нулей
np.zeros((2, 3))

# + colab={"base_uri": "https://localhost:8080/", "height": 68} executionInfo={"elapsed": 14737, "status": "ok", "timestamp": 1598902935996, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="AaJSBHSdgtCY" outputId="48d926ab-9bcd-4cbe-e378-35cd4444d096" _cell_id="LBY02bChBOrbCYNx"
# Явное создание массива единиц
np.ones((3, 2))

# + colab={"base_uri": "https://localhost:8080/", "height": 68} executionInfo={"elapsed": 14682, "status": "ok", "timestamp": 1598902935999, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="8_elMSoK7wQL" outputId="7f847991-56fc-4d28-b526-55634ffb2470" _cell_id="mGwjOLEsRCbRfWmo"
# Создание массива, заполненного константным значением
np.full((3, 4), 5)

# + colab={"base_uri": "https://localhost:8080/", "height": 68} executionInfo={"elapsed": 14596, "status": "ok", "timestamp": 1598902936003, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="iNN2C908gwUB" outputId="1ba59262-2d9f-47b2-c35a-0566e7f4b2a9" _cell_id="uDgdXNVSdes92eP9"
# 2D массив с единичной главной диагональю
# (*) В этой функции размерность задается не кортежем, а отдельными аргументами
np.eye(3, 2)

# + colab={"base_uri": "https://localhost:8080/", "height": 51} executionInfo={"elapsed": 14510, "status": "ok", "timestamp": 1598902936006, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="x8cGz7nIhbbE" outputId="e2a9a259-0b9e-4e3a-e4da-8cb225d5e9ef" _cell_id="Kd7jXLMxvO6mA8R6"
# Создание массива нулей с такой же размерностью, как уже существующий
arr_2d = np.array([[1, 2, 3], [4, 5, 6]])

np.zeros_like(arr_2d)

# + colab={"base_uri": "https://localhost:8080/", "height": 51} executionInfo={"elapsed": 14423, "status": "ok", "timestamp": 1598902936010, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="BqDTBiWzhj9R" outputId="ddc6ae91-5518-4ce2-e29e-d978fec22e0b" _cell_id="xzVLPyAgCPnHXigJ"
# Создание массива единиц с такой же размерностью, как уже существующий
arr_2d = np.array([[1, 2, 3], [4, 5, 6]])

np.ones_like(arr_2d)

# + colab={"base_uri": "https://localhost:8080/", "height": 51} executionInfo={"elapsed": 14351, "status": "ok", "timestamp": 1598902936023, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="MOqhVLYL7flG" outputId="4d4be8cd-eebd-48ff-c3a9-73021ea2ccec" _cell_id="B7U4yq1RoHOyhgef"
# Создание массива со случайными значениями в интервале [0; 1.0)
np.random.random((2,2))

# + colab={"base_uri": "https://localhost:8080/", "height": 34} executionInfo={"elapsed": 14270, "status": "ok", "timestamp": 1598902936027, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="PwWoeq26zmFm" outputId="08bd1868-479f-453b-8cb1-fe6256a5d641" _cell_id="oWQr8c5vKcSn3CRV"
# Аналог функции range
np.arange(start=1, stop=10, step=1.5)

# + colab={"base_uri": "https://localhost:8080/", "height": 51} executionInfo={"elapsed": 14187, "status": "ok", "timestamp": 1598902936031, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="adlhJ7Hnz-z9" outputId="2abddb47-a03b-419f-de1c-77fdb3b0ddfb" _cell_id="83gosctyNuShQBrA"
# Также создание диапазона значений, но уже с заданием количества элементов
# (*) stop уже входит в создаваемый диапазон
np.linspace(start=1, stop=2, num=10)

# + [markdown] id="S-szHgm6hq7X"
# ## Хитрая индексация

# + [markdown] id="LYFlLDO5huxy"
# Индексация в Python не ограничивается заданием конкретных индексов для получения значений в контейнерах (стандартных или массивов `ndarray`). Существуют специальные символы и подходы для работы с диапазонами данных, которые не только упрощают и улучшают код, но и выполняются более быстро, нежели проходы по массивам циклом.
#
# Начнём со знакомства с символом `:`, который позволяет задавать диапазон индексов для чтения/записи контейнеров.

# + id="9UClHM52huJi" _cell_id="sBIj4RaIPMbeDjkn"
# Для начала на простом списке (1D массива)
# Следующее создание массива можно заменить list(range(1, 11))
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# + colab={"base_uri": "https://localhost:8080/", "height": 68} executionInfo={"elapsed": 14107, "status": "ok", "timestamp": 1598902936041, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="eltg4vei7P2R" outputId="d71b442c-4165-4f8b-e3cd-9f94a782d6b2" _cell_id="u679QwCablF5ZyMl"
# Простая индексация
print(arr[0])
print(arr[-2])
print(arr[5])

# + [markdown] id="dzWHdiZw8GlN"
# Для получения подмассива (части массива) или записи в подмассив используется нотация $$index_{start}:index_{end}:step$$
#
# - $index_{start}$ - индекс начала подмассива
# - $index_{end}$ - индекс конца подмассива
# - $step$ - шаг подмассива

# + colab={"base_uri": "https://localhost:8080/", "height": 34} executionInfo={"elapsed": 14042, "status": "ok", "timestamp": 1598902936044, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="w3x1hjul7ZnM" outputId="c888219f-ebfc-40c3-c462-5a186bf6ece7" _cell_id="jWXovYkKBstJ5BzC"
# Получение части массива c 3-го по 9-й элемент (не включительно) 
    #   или со 2-го по 8-й (при индексации с нуля)
    #   с шагом 2 
print(arr[2:8:2])

# + colab={"base_uri": "https://localhost:8080/", "height": 34} executionInfo={"elapsed": 13986, "status": "ok", "timestamp": 1598902936047, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="UeghJuRp9XSG" outputId="4e508fa8-00e3-4a8c-98a5-7772aae248c9" _cell_id="5E6aiMy7YyGtWMTR"
# Если шаг не задан, то он равен единице (при этом второй раз : не пишется)
print(arr[2:8])

# + colab={"base_uri": "https://localhost:8080/", "height": 34} executionInfo={"elapsed": 13828, "status": "ok", "timestamp": 1598902936054, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="f2et5vq_9YQ0" outputId="9d8d00aa-6cff-4397-87f7-60d0ec48710e" _cell_id="7ysrifnnHNimsrZl"
# Шаг может быть и отрицательным (индексы меняются местами)
print(arr[8:2:-1])

# + colab={"base_uri": "https://localhost:8080/", "height": 51} executionInfo={"elapsed": 13635, "status": "ok", "timestamp": 1598902936075, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="THxAw6mR9ZK1" outputId="92559d71-b762-4030-9b1f-a0be263728b6" _cell_id="PEaWUFrVJrFuTTsL"
# Если не задавать index_start или index_end, 
#   то они будут равны индексу начала и конца массива
print(arr[2:])
print(arr[:8])

# + colab={"base_uri": "https://localhost:8080/", "height": 51} executionInfo={"elapsed": 13402, "status": "ok", "timestamp": 1598902936079, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="Ti3t0ZVa9gfe" outputId="595c578b-9dea-4913-aef8-11c0b5e4fbad" _cell_id="wrqo7bXLBNfncfLD"
# Можно комбинировать один из индексов и шаг
print(arr[2::2])
print(arr[:8:3])

# + colab={"base_uri": "https://localhost:8080/", "height": 34} executionInfo={"elapsed": 13163, "status": "ok", "timestamp": 1598902936082, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="xj257QBQ-LsQ" outputId="503be9fe-e300-42ef-d32b-c21a3620748e" _cell_id="qmVdP4UG8OA9XXR2"
# И не забываем, что все трюки работают и на запись
new_arr = list(range(1, 11))

new_arr[1:5] = arr[:4]
print(new_arr)

# + colab={"base_uri": "https://localhost:8080/", "height": 34} executionInfo={"elapsed": 12964, "status": "ok", "timestamp": 1598902936085, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="UiQHCjYPAreX" outputId="cb978a3f-2dbd-485e-f844-da07469fb340" _cell_id="MsbSOh6Jg5sVKgdY"
# Не самая полезная, но все же запись (получить весь диапазон)
print(arr[:])

# + [markdown] id="Y1CX7Bpi91aI"
# ### Задание - подумаем
#
# Объясните результат операции:

# + colab={"base_uri": "https://localhost:8080/", "height": 34} executionInfo={"elapsed": 12883, "status": "ok", "timestamp": 1598902936089, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="HRS-xvPK97di" outputId="6a52db7a-8e0e-44a8-da51-fe16272a0838" _cell_id="mg1tPddy2D1xOais"
print(arr[:5:-2])

# + [markdown] id="CmTGLk0n_K8w"
# ### Задание - учимся обращать
#
# Получите перевернутый список:

# + colab={"base_uri": "https://localhost:8080/", "height": 34} executionInfo={"elapsed": 12829, "status": "ok", "timestamp": 1598902936120, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="7XJaNnuf_TUl" outputId="e21fee78-af36-4f31-8faa-7fcb9674cce7" _cell_id="wyZhrcqDGjkrTWwu"
data = list(range(10))
print(data)

# TODO - [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

# + [markdown] id="TT3t4yG5B8XW"
# ### Задание - подмассив
#
# Получите массив без первого и двух последних элементов:

# + colab={"base_uri": "https://localhost:8080/", "height": 34} executionInfo={"elapsed": 12757, "status": "ok", "timestamp": 1598902936123, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="evJXMrHrCFFj" outputId="892b0310-b048-4fda-a782-80fd699bcc6e" _cell_id="BUxf5XoTKIeOziIQ"
data = list(range(10))
print(data)

# TODO - [1, 2, 3, 4, 5, 6, 7]

# + [markdown] id="yr_Sgpxeg7nG"
# ## Хитрая индексация в матрицах

# + [markdown] id="4vzYWeA1_nL4"
# Работа с одномерными списками удобна даже через класс `list`, но 2D массивы уже удобнее использовать через библиотеку numpy. Использование numpy никак не ограничивает применение такой индексации, так что можно делать много классных штук:

# + colab={"base_uri": "https://localhost:8080/", "height": 68} executionInfo={"elapsed": 12687, "status": "ok", "timestamp": 1598902936126, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="roSKMhOd_7HG" outputId="382d14d8-346d-4cdd-86ba-ee435688e507" _cell_id="fCbzXSa7omSY03y5"
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(arr)

# + [markdown] id="bw7Re8l_ASG0"
# В индексации numpy есть очень полезное правило: если последующие индексы не заданы, то они принимаются как "весь диапазон". Например, в двумерном массиве мы индексируем по двум числам $[3, 2]$. Если в 2D массиве задать индекс $[3]$, то это эквивалентно индексации $[3, :]$, то есть третий ряд, все колонки.
#
# В плане предшествующих индексов это не работает, поэтому, чтобы получить целую колонку, надо индексировать $[:, 2]$.

# + colab={"base_uri": "https://localhost:8080/", "height": 51} executionInfo={"elapsed": 12649, "status": "ok", "timestamp": 1598902936159, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="KhiA2r2-AK5d" outputId="17c7fd29-026f-4b4e-8818-bd8a522e4dcf" _cell_id="mUJIQpC1qmyyYabn"
# Получим вторую строку массива
print(arr[2])
print(arr[2, :])

# + colab={"base_uri": "https://localhost:8080/", "height": 34} executionInfo={"elapsed": 12160, "status": "ok", "timestamp": 1598902936175, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="dF2bEK7dBU5C" outputId="a25a0f1f-e267-4341-8fd5-3b231c433c16" _cell_id="qQVaxYfY8Z0zLKyN"
# Получим первую колонку массива
print(arr[:, 1])

# + colab={"base_uri": "https://localhost:8080/", "height": 34} executionInfo={"elapsed": 12066, "status": "ok", "timestamp": 1598902936192, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="MjkcYLIUBoIZ" outputId="30fbbc58-4423-4233-d4ef-781f58370b01" _cell_id="1QHRh4D31p3v0tWv"
# Получить первые два элемента (первые две колонки) первого ряда
print(arr[1, :2])

# + colab={"base_uri": "https://localhost:8080/", "height": 120} executionInfo={"elapsed": 11999, "status": "ok", "timestamp": 1598902936194, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="nsjlZWVkC4JV" outputId="3deff8b2-34f3-49a8-fc2c-fae947dd1ea0" _cell_id="6TxI23T13Nv43BjT"
# Можно повторять целые части массива
#   (но при этом должны соотноситься размерности)
# ndarray.copy() - функция копирования массива
# Копируем, чтобы не изменить оригинальный
new_arr = arr.copy()
print(arr)

new_arr[2, :] = arr[1, :]
print(new_arr)

# + colab={"base_uri": "https://localhost:8080/", "height": 68} executionInfo={"elapsed": 11944, "status": "ok", "timestamp": 1598902936211, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="Cok9ET1xDpHL" outputId="2124083d-d58a-4f28-c40d-1119fb083bb3" _cell_id="CAzKMKMtzS7MLxTi"
# При этом, такая индексация - это новый массив со своей размерностью.
print(arr[:2, :2])
print(arr[:2, :2].shape)

# + colab={"base_uri": "https://localhost:8080/", "height": 68} executionInfo={"elapsed": 11871, "status": "ok", "timestamp": 1598902936214, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="cc0YJBmSEDlb" outputId="5679e9c3-baad-4c17-ace9-872db748ce6d" _cell_id="3Bm6GXrfiMcGhApI"
# В качестве индексов можно также задавать другие массивы
# Получаем первую и последнюю колонки
print(arr[:, [0, -1]])

# + colab={"base_uri": "https://localhost:8080/", "height": 68} executionInfo={"elapsed": 11820, "status": "ok", "timestamp": 1598902936226, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="296Ww5MDFaY4" outputId="362ee527-43c8-41a4-e0de-18820b1255c9" _cell_id="zZgfoSdWo1Y2a5hB"
# И таким образом никто не заставляет писать в том же порядке индексы
# Перемешаем ряды
print(arr[[2, 0, 1], :])

# + colab={"base_uri": "https://localhost:8080/", "height": 51} executionInfo={"elapsed": 11775, "status": "ok", "timestamp": 1598902936239, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="RFkxEluyFpZb" outputId="fcb59443-3191-423d-f9d9-089eaad16346" _cell_id="t2RB7Jfw2XsG91ry"
# Также, можно комбинировать способы задания
print(arr[[2, 0], [1, 3]])
# То же самое, только первая запись дает массив
print(arr[2, 1], arr[0, 3])

# + colab={"base_uri": "https://localhost:8080/", "height": 120} executionInfo={"elapsed": 11707, "status": "ok", "timestamp": 1598902936242, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="EKQkjUnxE4vN" outputId="6fffec76-9805-47bd-ca1f-76f0fc328bd9" _cell_id="bjZ9mXwE16IWDOGb"
# Создаем список возможных индексов для рядов массива
row_indices = list(range(arr.shape[0]))
print(row_indices)

# Переворачиваем его
row_indices = list(reversed(row_indices))
print(row_indices)

# Используем для индексации
print('----------------')
print(arr[row_indices])

# + [markdown] id="4jVVCGMSCPWu"
# ### Задание - еще больше срезаем
#
# Получите массив без крайних рядов и колонок (по одной с каждой стороны)

# + colab={"base_uri": "https://localhost:8080/", "height": 102} executionInfo={"elapsed": 11658, "status": "ok", "timestamp": 1598902936259, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="rJegDeQ6CcTD" outputId="c6fa250f-ba84-4cbb-c143-39c1119537e5" _cell_id="FzD1A7PBHrrkn79u"
data = np.random.randint(low=0, high=10, size=(5, 6))
print(data)

# TODO - центральная часть массива размером (3, 4)

# + [markdown] id="7R_2MeNRGsNq"
# ### Задание - кручу-верчу - запутать хочу
#
# Произведите перемешивание колонок с помощью функции `numpy.random.permutation()`:
#
# <details>
# <summary>Подсказка</summary>
#
# Перемешать колонки можно путем перемешивания списка возможных индексов колонок (`range(<col_count>)`) и затем индексацией этого списка по индексам колонок (`[:, cols]`).
# </details>

# + colab={"base_uri": "https://localhost:8080/", "height": 68} executionInfo={"elapsed": 11605, "status": "ok", "timestamp": 1598902936265, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="EawZBVacHHk4" outputId="7d7259ad-cbc6-4c64-eada-fa031bba1f62" _cell_id="9pv28BlOl7zeoNdw"
data = np.random.randint(low=0, high=10, size=(3, 6))
print(data)

# TODO - такой же массив, но со случайной перестановкой колонок

# + [markdown] id="RKssiBX6IWQ4"
# ## Типы данных в массивах

# + [markdown] id="1W373guIIYpQ"
# Массивы в numpy имеют не только размер, но и конкретный тип данных, которые хранятся внутри массива. При создании массива почти все функции создания имеют аргумент `dtype`, который означает, с каким типом создать данным массив. Также, класс `ndarray` имеет атрибут `dtype`, который означает тип хранимых данных. 

# + [markdown] id="RkaZp3yUQ2l9"
# Подробнее можно прочитать в [документации](https://numpy.org/doc/stable/reference/arrays.dtypes.html).

# + colab={"base_uri": "https://localhost:8080/", "height": 34} executionInfo={"elapsed": 11556, "status": "ok", "timestamp": 1598902936280, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="hhX2FD0xJC50" outputId="4def6a72-cd1f-4f9f-90f7-6d09386c40b0" _cell_id="Vbpi1UzPZFpmV8Dy"
# Создадим массив без задания типа - тип будет определен автоматически
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(arr.dtype)

# int, так как все элементы являются целочисленными

# + colab={"base_uri": "https://localhost:8080/", "height": 34} executionInfo={"elapsed": 11506, "status": "ok", "timestamp": 1598902936295, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="pVSghFu5JQTO" outputId="187212df-9cfc-4068-f3a5-5d4020692e77" _cell_id="wr7XJTH7fmIqRAMO"
# Изменим один элемент на вещественный
arr = np.array([[1.5, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(arr.dtype)

# Один из элементов float, поэтому весь массив будет float

# + colab={"base_uri": "https://localhost:8080/", "height": 68} executionInfo={"elapsed": 11454, "status": "ok", "timestamp": 1598902936307, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="OfAofWauJePj" outputId="b8fdcee4-1582-4d97-d20c-c067c74135f2" _cell_id="HebuV0ZwUVmYw34z"
# Зададим явно тип массива
# Хоть массив и содержит вещественные числа
# мы создаем массив целочисленных, что приводит
# к округлению
arr = np.array([[1.1, 1.6, 2.4], [-1.7, 2.6, -1.2]], dtype=int)
print(arr)
print(arr.dtype)

# + colab={"base_uri": "https://localhost:8080/", "height": 137} executionInfo={"elapsed": 11436, "status": "ok", "timestamp": 1598902936348, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="Nj1UkwjDKBr1" outputId="14e4143a-e244-495d-9bc6-0460b4949484" _cell_id="fVM4noinXEOVYRnk"
# Создаем массив вещественных
arr = np.array([[1.1, 1.6, 2.4], [-1.7, 2.6, -1.2]])
print(arr)
print(arr.dtype)
print('----------')
# Но в какой-то момент нам нужно привести массив к целочисленным
# Воспользуемся методом ndarray.astype()
arr = arr.astype(int)
print(arr)
print(arr.dtype)

# + colab={"base_uri": "https://localhost:8080/", "height": 85} executionInfo={"elapsed": 11369, "status": "ok", "timestamp": 1598902936356, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjZicdeEga0uI_adjvPG_ydk4aC9pHcJhRxHdlu=s64", "userId": "01450359895113891365"}, "user_tz": -180} id="4Zv5Ss7KKa77" outputId="a7a1ff9d-4bd7-482c-8b6e-b83de93d48c0" _cell_id="I1iq8cvRQVaGHvlo"
# При этом попытки записать в целочисленный массив 
# вещественное число приводят к округлению
arr = np.array([[1.1, 1.6, 2.4], [-1.7, 2.6, -1.2]], dtype=int)
print(arr)

arr[0, 1] = 10.12
print(arr)

StarcoderdataJupyterScriptsDedupFiltered