.

Сделать репост в соц сети!

понедельник, 24 декабря 2018 г.

Снижение числа уровней категориальной переменной Pandas Python





Задачка простая, но мне она показалась очень интересной, и я вынес ее в блог.
Задача часто встречается в наших HR данных, смысл ее в том, что в категориальной переменной много уровней с очень низкой частотой, и мы должны эти уровни переменной вынести в один уровень "другое", чтобы анализ был корректным.

Решение


Загружаем библиотеки
import numpy as np
import pandas as pd
В качестве toy example такой датафрейм
df = pd.DataFrame({'Город':
'Москва Москва Москва Москва Москва Москва Санкт-Петербург Санкт-Петербург Санкт-Петербург Новосибирск Новосибирск Красноярск Магадан'
                   .split()})
df
 Город
0 Москва
1 Москва
2 Москва
3 Москва
4 Москва
5 Москва
6 Санкт-Петербург
7 Санкт-Петербург
8 Санкт-Петербург
9 Новосибирск
10 Новосибирск
11 Красноярск
12 Магадан
Сначала мы считаем количество значений
val = pd.value_counts(df['Город'])
val
Москва             6
Санкт-Петербург    3
Новосибирск        2
Магадан            1
Красноярск         1
Name: Город, dtype: int64
А потом пользуемся замечательной формулой pandas.Series.lt


mask = val.lt(2)
mask 
Москва             False
Санкт-Петербург    False
Новосибирск        False
Магадан             True
Красноярск          True
Name: Город, dtype: bool
Мы указали все города, частота которых менее 2 раз. А далее аналог формулы ЕСЛИ в excel
df['city']  = np.where(df['Город'].isin(val[mask].index),'другое',df['Город'] ).astype(object)
И проверяем
pd.crosstab(df['Город'], df['city'])
city      Москва Новосибирск Санкт-Петербург другое
Город    
Красноярск 0 0     0           1
Магадан         0 0     0           1
Москва         6 0     0           0
Новосибирск 0 2     0           0
Санкт-Петербург 0 0     3           0
Сошлось.
А если мы хотим задать порог не в абсолютных числах, а в %? Уровнем статистической значимости считают 5%, поэтому мы можем смело его задавать.
Правда я ниже укажу не 5, а 10 %, потому что в нашем датасете нет значений менее 5 %. Мы меняем только эту формулу, остальное все тоже самое
mask = (val/val.sum() * 100).lt(10)
Все. Можно применять

Комментариев нет:

Отправить комментарий