В этом модуле мы работаем с тремя метеостанциями за февраль 2025 года: в центре города, в аэропорту и в лесу за
городом. Каждая записывает по строке в день: номер дня, температуру, влажность в процентах и ветер в метрах
в секунду. Иногда датчик молчит — и в файле остаётся пустое поле. Посмотрим на файл аэропорта: метод строки
splitlines делит прочитанный текст на список строк файла, и мы напечатаем строки дней с 9-го по 14-й:
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 на таком файле падает — пустое
поле не число:
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-функции.
Загрузите файл data/station_center.csv целиком в center. Сохраните в gaps_by_col число пропусков
в каждом столбце, а в center_avg — среднюю температуру (столбец 1) без учёта пропусков.
np.genfromtxt("data/station_center.csv", delimiter=",", skip_header=1).np.isnan(center).sum(axis=0); средняя — np.nanmean(center[:, 1]).Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
center = ...
gaps_by_col = ...
center_avg = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
center = np.genfromtxt("data/station_center.csv", delimiter=",", skip_header=1)
gaps_by_col = np.isnan(center).sum(axis=0)
center_avg = np.nanmean(center[:, 1])Что будет, если забыть про заголовок? 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. Какой будет форма массива?
genfromtxt не падает на тексте, а делает из заголовка строку nan — получается 29 строк.Заполнить при чтении: 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 в феврале — это заметная оттепель, и такие «оттепели» сдвинут среднюю.
Загрузите столбец температуры (1) аэропорта дважды: в zero_temp — с filling_values=0, в temp — с
пропусками. Сохраните в zero_avg среднюю по zero_temp, а в true_avg — среднюю по temp без пропусков.
delimiter=",", skip_header=1, usecols=1; для zero_temp добавьте filling_values=0.true_avg = np.nanmean(temp).Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
zero_temp = ...
temp = ...
zero_avg = ...
true_avg = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
zero_temp = np.genfromtxt("data/station_airport.csv", delimiter=",", skip_header=1, usecols=1, filling_values=0)
temp = np.genfromtxt("data/station_airport.csv", delimiter=",", skip_header=1, usecols=1)
zero_avg = zero_temp.mean()
true_avg = np.nanmean(temp)Пять «нулевых» дней подняли среднюю почти на градус: −3.8 вместо −4.6 °C.
Заполнить потом: np.nan_to_num
Если массив уже загружен, пропуски заменяет np.nan_to_num(a, nan=значение). Он возвращает новый массив,
исходный не меняется. Без nan= пропуски станут нулями — с той же опасностью:
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) из прошлого урока, только короче.
Загрузите файл data/station_forest.csv в forest и сохраните в humidity его столбец влажности (номер 2).
В hum_filled сохраните влажность, где пропуск заменён средней влажностью по известным дням.
forest[:, 2].np.nan_to_num(humidity, nan=np.nanmean(humidity)).Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
forest = ...
humidity = ...
hum_filled = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
forest = np.genfromtxt("data/station_forest.csv", delimiter=",", skip_header=1)
humidity = forest[:, 2]
hum_filled = np.nan_to_num(humidity, nan=np.nanmean(humidity))Итоги
np.genfromtxt(путь, delimiter=",", skip_header=1)читает CSV с пустыми полями; пустое поле →nan.- Без
skip_headerзаголовок не вызывает ошибку, а становится строкойnan— проверяйте форму. filling_values=заполняет пропуски при чтении,np.nan_to_num(a, nan=…)— после.- Ноль — тоже данные: заполняйте им только то, где ноль значит «ничего не было».