Нашли ошибку?
Скачать чистый
урок 2 из 4≈ 15 минупражнения: 0 из 3

Файлы с пропусками

Загрузить CSV с пустыми полями — np.genfromtxt превращает их в NaN; заполнить пропуски при чтении filling_values= или потом np.nan_to_num и понять, чем опасен ноль.

Python запустится при первом выполнении

В этом модуле мы работаем с тремя метеостанциями за февраль 2025 года: в центре города, в аэропорту и в лесу за городом. Каждая записывает по строке в день: номер дня, температуру, влажность в процентах и ветер в метрах в секунду. Иногда датчик молчит — и в файле остаётся пустое поле. Посмотрим на файл аэропорта: метод строки splitlines делит прочитанный текст на список строк файла, и мы напечатаем строки дней с 9-го по 14-й:

[ ]Пустые поля в CSV
with open("data/station_airport.csv") as f:
    lines = f.read().splitlines()
for line in lines[9:15]:
    print(line)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
9,-7.8,81,3.2
10,-7.6,79,4.4
11,,82,3.0
12,,79,2.4
13,,82,5.6
14,-6.9,75,2.7

У дней 11–13 между запятыми пусто: температуры нет. Знакомый np.loadtxt на таком файле падает — пустое поле не число:

[ ]loadtxt не читает пустые поляошибка: ValueError
import numpy as np

np.loadtxt("data/station_airport.csv", delimiter=",", skiprows=1)
Ошибкасохранённый · нажмите «Выполнить», чтобы получить свой
ValueError: could not convert string '' to float64 at row 10, column 2.

np.genfromtxt

np.genfromtxt — «сгенерировать из текста» — читает CSV так же, как loadtxt, но пустое поле превращает в nan. Параметры почти те же: delimiter=",", usecols=, только строки заголовка пропускает skip_header= (а не skiprows=):

[ ]Файл аэропорта с пропусками
airport = np.genfromtxt("data/station_airport.csv", delimiter=",", skip_header=1)
print(airport.shape)
print(airport[8:14])
print(np.isnan(airport[:, 1]).sum(), "дней без температуры")
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
(28, 4)
[[ 9.  -7.8 81.   3.2]
 [10.  -7.6 79.   4.4]
 [11.   nan 82.   3. ]
 [12.   nan 79.   2.4]
 [13.   nan 82.   5.6]
 [14.  -6.9 75.   2.7]]
5 дней без температуры

Дальше это обычный массив: пропуски ищет np.isnan, итоги без них считают nan-функции.

[ ]Упражнение 1Станция в центре решено

Загрузите файл data/station_center.csv целиком в center. Сохраните в gaps_by_col число пропусков в каждом столбце, а в center_avg — среднюю температуру (столбец 1) без учёта пропусков.

center = ...
gaps_by_col = ...
center_avg = ...

Что будет, если забыть про заголовок? loadtxt в таком случае падал с ошибкой. genfromtxt не падает — слова заголовка тоже не числа, и он молча превращает их в NaN:

[ ]Заголовок стал строкой пропусков
raw = np.genfromtxt("data/station_center.csv", delimiter=",")
print(raw.shape)
print(raw[:3])
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
(29, 4)
[[ nan  nan  nan  nan]
 [ 1.  -5.3 82.   1.9]
 [ 2.  -5.3 84.   1.9]]
Вопрос

Файл data/station_forest.csv загрузили без skip_header. Какой будет форма массива?

Заполнить при чтении: filling_values

Параметр filling_values= сразу подставляет в пустые поля заданное число:

[ ]Пропуски сразу заменены нулём
filled_demo = np.genfromtxt("data/station_airport.csv", delimiter=",", skip_header=1, filling_values=0)
print(filled_demo[9:14])
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
[[10.  -7.6 79.   4.4]
 [11.   0.  82.   3. ]
 [12.   0.  79.   2.4]
 [13.   0.  82.   5.6]
 [14.  -6.9 75.   2.7]]

Удобно, но осторожно: ноль — тоже значение. Иногда он допустим — например, продажи в день, когда магазин был закрыт. А 0 °C в феврале — это заметная оттепель, и такие «оттепели» сдвинут среднюю.

[ ]Упражнение 2Чем опасен ноль решено

Загрузите столбец температуры (1) аэропорта дважды: в zero_temp — с filling_values=0, в temp — с пропусками. Сохраните в zero_avg среднюю по zero_temp, а в true_avg — среднюю по temp без пропусков.

zero_temp = ...
temp = ...
zero_avg = ...
true_avg = ...

Пять «нулевых» дней подняли среднюю почти на градус: −3.8 вместо −4.6 °C.

Пояснение с ответом появится, когда решите упражнение «Чем опасен ноль».

Заполнить потом: np.nan_to_num

Если массив уже загружен, пропуски заменяет np.nan_to_num(a, nan=значение). Он возвращает новый массив, исходный не меняется. Без nan= пропуски станут нулями — с той же опасностью:

[ ]np.nan_to_num
row = np.array([2.0, np.nan, 5.0])
print(np.nan_to_num(row))
print(np.nan_to_num(row, nan=-1.0))
print(row)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
[2. 0. 5.]
[ 2. -1.  5.]
[ 2. nan  5.]

Это то же самое, что np.where(np.isnan(a), значение, a) из прошлого урока, только короче.

[ ]Упражнение 3Влажность в лесу решено

Загрузите файл data/station_forest.csv в forest и сохраните в humidity его столбец влажности (номер 2). В hum_filled сохраните влажность, где пропуск заменён средней влажностью по известным дням.

forest = ...
humidity = ...
hum_filled = ...

Итоги

  • np.genfromtxt(путь, delimiter=",", skip_header=1) читает CSV с пустыми полями; пустое поле → nan.
  • Без skip_header заголовок не вызывает ошибку, а становится строкой nan — проверяйте форму.
  • filling_values= заполняет пропуски при чтении, np.nan_to_num(a, nan=…) — после.
  • Ноль — тоже данные: заполняйте им только то, где ноль значит «ничего не было».

Подробнее в справочнике

Нашли ошибку?