pandas CategoricalDtype: почему astype заменяет значения на NaN

При преобразовании в pd.CategoricalDtype допустимы только значения из categories. Значение вне заданного списка становится пропуском. Поэтому появление NaN после astype не обязательно означает пропуск в исходных данных.

Проверьте значения до преобразования

Сравнение через isin(categories) помогает найти значения вне шкалы заранее. Параметр ordered=True задаёт порядок категорий для сравнения и сортировки, но не добавляет новые категории автоматически. Сохраните исходный столбец, если нужно показать пользователю, какие значения не прошли проверку.

Пример на других данных

import pandas as pd
s = pd.Series(["high", "unknown", "low"])
dtype = pd.CategoricalDtype(categories=["low", "high"], ordered=True)
print((~s.isin(dtype.categories)).tolist())
converted = s.astype(dtype)
print(converted.isna().tolist())
print(converted.dropna().sort_values().tolist())

Результат:

[False, True, False]
[False, True, False]
['low', 'high']

Решите задачу

Ниже — условие и редактор Python с проверкой без регистрации. Пример выше показывает приём на других данных; для задачи соблюдайте её формат ввода и результата. Курс NumPy и pandas помогает пройти темы по порядку.

Категориальный тип и значения вне шкалы: NaN при astype и категориальная сортировка

Что уже дано

Проверяющая система запускает вашу программу и подаёт данные через stdin. Никаких заранее созданных переменных нет — вы читаете всё сами.

Что нужно сделать

Напишите программу, которая работает с таблицей задач и демонстрирует поведение CategoricalDtype при наличии значений, не входящих в список категорий.

  1. Читает из stdin целое число n — количество строк.
  2. Читает следующие n строк; каждая содержит два токена через пробел: task_id (целое число) и status (строка без пробелов). Пример строки: 1 открыта.
  3. Строит pd.DataFrame с именем df из словаря списков с ключами 'task_id' (int) и 'status' (str).
  4. Шаг A. Подсчёт значений вне шкалы. Создаёт множество допустимых значений valid = {'открыта', 'в_работе', 'закрыта'}. Считает количество строк, где status не входит в valid, через булеву маску. Выводит outside=<k> — целое число.
  5. Шаг B. Создание и применение CategoricalDtype. Создаёт cat_dtype = pd.CategoricalDtype(categories=['открыта', 'в_работе', 'закрыта'], ordered=True) и присваивает тип столбцу df['status'] через astype. Результат сохраняет обратно в df['status'].
  6. Шаг C. Подсчёт NaN после astype. Выводит nan_after=<k> — количество NaN в df['status'] после преобразования (значения вне шкалы стали NaN).
  7. Шаг D. Сортировка. Сортирует df по 'status' через df.sort_values('status'), сохраняет в df_sorted. Выводит значения df_sorted['status'].tolist() как строку Python (включая nan-значения, которые окажутся в конце или начале — pandas помещает их последними по умолчанию).
  8. Шаг E. Проверка dtype и ordered. Выводит str(df['status'].dtype) и str(df['status'].cat.ordered) — каждое на отдельной строке.

Ввод и вывод

Программа читает stdin и пишет в stdout.

Формат ввода

n
task_id1 status1
task_id2 status2
...

Формат вывода

Пять строк:

outside=<k>
nan_after=<k>
<df_sorted['status'].tolist() как строка Python>
<dtype>
<cat.ordered>

Пример

Ввод
6
1 открыта
2 в_работе
3 закрыта
4 отложена
5 открыта
6 закрыта
Вывод
outside=1
nan_after=1
['открыта', 'открыта', 'в_работе', 'закрыта', 'закрыта', nan]
category
True
РешениеPython

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

Отправьте решение, чтобы увидеть результаты тестов.

Связанные задачи