Домашнє завдання

NumPy: масиви

Дані тут інші, ніж у лекції, — навмисно: якщо та сама механіка працює на чужій задачі, значить, справа не в завченому прикладі. Працюємо з показаннями метеостанцій: таблиця «станція × година», у комірці температура в градусах. Усе роби в окремому файлі pogoda.py або в новому зошиті — практику не редагуй, вона знадобиться для звірки.

Дані генеруй так і ніяк інакше, щоб числа збігались із критеріями нижче:

import numpy as np

генератор = np.random.default_rng(2024)
температури = генератор.normal(12.0, 6.0, size=(6, 24)).round(1)   # 6 станцій × 24 години
станції = ["Лиман", "Гора", "Поле", "Ліс", "Берег", "Місто"]

рівень 1Рівень 1 — База

Роздивись масив і навчись діставати з нього шматки за координатами.

  1. Надрукуй паспорт масиву: shape, ndim, size, dtype, itemsize, nbytes — кожне з підписом, що воно означає.
  2. Порахуй, скільки памʼяті займав би той самий набір чисел у вигляді вкладеного списку. Заміряй чесно через tracemalloc, а не на око.
  3. Дістань і надрукуй з підписами: температуру на станції «Поле» о 15-й годині; увесь день станції «Берег»; 8-му годину на всіх станціях; прямокутник «станції 1-3, години 6-12».
  4. Переведи весь масив у Фаренгейти однією векторною дією (градуси * 9 / 5 + 32) — без жодного циклу.

Зроблено, якщо:


рівень 2Рівень 2 — Плюс

Тепер підсумки, осі, транслювання й маски — і жодного for по елементах.

  1. Порахуй середню температуру по станціях і по годинах. Надрукуй обидва масиви з підписами й поясни в коментарі, чому в одному випадку axis=1, а в іншому axis=0.
  2. Знайди для кожної станції її найтеплішу годину — через argmax з віссю, а не циклом.
  3. Побудуй масив аномалії = наскільки кожне вимірювання відхиляється від середнього по своїй станції. Скористайся keepdims=True.
  4. Побудуй масив холодні — маску «нижче за нуль». Порахуй, скільки таких вимірювань усього і скільки їх на кожній станції.
  5. Одним рядком зроби безпечні — копію масиву, у якій усе нижче за нуль замінено на 0, а решта лишилась як була. Оригінал при цьому має вціліти.

Зроблено, якщо:


рівень 3Рівень 3 — Виклик

Досліди межі: де вигляд кусає, де транслювання падає й де векторизація перестає вигравати.

  1. Напиши дві функції з однаковою логікою — «обнулити першу годину доби на всіх станціях»: зіпсувати(масив), яка пише прямо у зріз переданого масиву, і безпечно(масив), яка починає з дані = масив.copy(). Доведи assert-ами: після безпечно оригінал цілий, після зіпсувати — ні. Другий assert спіймай через try/except AssertionError, щоб файл усе одно дорахувався до кінця.
  2. Збери таблицю поєднань форм: для пар (6, 24) з (24,), (6,), (6, 1), (1, 24), (24, 1), а також окремо для пари (6, 1) з (1, 24) спробуй додавання й запиши в таблицю або форму результату, або текст помилки. Кожен рядок поясни одним реченням: яка вісь із якою зіткнулась.
  3. Порівняй швидкість на трьох розмірах — 1 000, 100 000 і 5 000 000 елементів — для трьох способів однієї дії × 9 / 5 + 32: цикл for зі списком, спискове включення, векторна дія. Виміряй timeit.repeat(..., repeat=7) і бери мінімум. Побудуй табличку з трьох рядків і чотирьох стовпців.
  4. Знайди в цій табличці розмір, на якому пришвидшення падає порівняно з попереднім рядком, і поясни причину числом: порахуй nbytes масиву на кожному розмірі й назви, з якого моменту дані перестали вміщуватись у кеш процесора.
  5. Порахуй ту саму таблицю аномалій із рівня 2 у трьох типах: float64, float32 і float16. Для кожного надрукуй nbytes і максимальне відхилення від float64-версії. Зроби висновок одним реченням: де економія памʼяті виправдана, а де вже ні.

Зроблено, якщо:


Підказки