Мне удалось воспроизвести вашу проблему следующим образом:
>>> df = pd.DataFrame()
>>> df['protocol'] = pd.Categorical(['A', 'B', 'C', 'D', 'A'])
>>> df.select_dtypes('object')
Empty DataFrame
Columns: []
Вы можете видеть, что последняя строка, соответствующая
categorical_subset = df.select_dtypes('object')
, вероятно, возвращает пустой DataFrame
( если есть сомнения, было бы хорошо проверить, что categorical_subset
действительно содержит то, что вы ожидали, что он будет содержать.
Это потому, что когда вы переназначили df['protocol']
, который изначально содержал строки, pd.Categorical
, его dtype (как и другие категориальные столбцы) больше не object
, а category
):
>>> df.dtypes
protocol category
dtype: object
(этот вывод выглядит немного запутанным; в нем говорится, что dtype для protocol
равен category
, но под ним написано dtype: object
: возвращаемое значение DataFrame.dtypes
на самом деле является Series
со столбцами для имени столбца и dtype, поэтому обманчивый dtype: object
внизу относится к dtype этой серии).
Вероятно, это именно то, что вы действительно хотели:
>>> df.select_dtypes('category')
protocol
0 A
1 B
2 C
3 D
4 A
На самом деле, в документации для select_dtypes
:
Чтобы выбрать Pandas категориальные типы, используйте * 10 37 *
Вышеупомянутое является хорошим примером того, как создать минимальный воспроизводимый пример , а также в целом, как отлаживать небольшие программы. Сначала мы обратили внимание на проблемную область, строку
categorical_subset.columns.drop("protocol")
, где, по-видимому, не должно быть столбца с именем 'protocol'
. Затем мы просто работаем в обратном направлении к тому, как был создан categorical_subset
(мы вызвали df.select_dtypes('object')
в нашем исходном фрейме данных). И кроме этого, все, что нам нужно, это пример фрейма данных с несколькими pd.Categorical
столбцами.