Проставление рейтинга строчкам в pandas dataframe с изменяемым шагом
Имеется датафрейм(пример):
import pandas as pd
d = {'stores': ['AG21', 'AG41', 'AG85', 'AG45',
'AG31', 'AS25', 'AR81', 'AA43',
'AG21', 'AD83', 'AA36', 'AG55',
'AT58', 'AD11', 'AH32', 'AE17'],
'linear': [430, 145 , 120, 180,
250, 250, 250, 320,
376, 390, 420, 580,
350, 190, 125, 390]}
df = pd.DataFrame(data=d)
df = df.sort_values(by='linear')
df
В колонку linear заходят значения от расчетов из другого кода и сортируются по возрастанию.
Затем, вручную, строчкам проставляются рейтинги от 1 до 6. К примеру, к датафрейму выше(к колонке linear), вручную бы проставились примерно такие рейтинги(раскиданы на глаз)
import pandas as pd
d = {'stores': ['AG21', 'AG41', 'AG85', 'AG45',
'AG31', 'AS25', 'AR81', 'AA43',
'AG21', 'AD83', 'AA36', 'AG55',
'AT58', 'AD11', 'AH32', 'AE17'],
'linear': [430, 145 , 120, 180,
250, 250, 250, 320,
376, 390, 420, 580,
350, 190, 125, 390]}
df = pd.DataFrame(data=d)
df = df.sort_values(by='linear')
df['ratings'] = 1,1,1,2,2,3,3,3,4,4,4,5,5,5,5,6
df
Они приблизительно ставятся в зависимости от схожести значений с верхними строчками(после сортировки) с небольшим шагом и если шаг сильно отличается, то рейтинг возрастает.
НО не во всех случаях есть шестой или пятый рейтинг. Пример ниже:
import pandas as pd
d = {'stores': ['AG21', 'AG41', 'AG85', 'AG45',
'AG31', 'AS25', 'AR81', 'AA43'],
'linear': [330, 145 , 120, 180,
250, 150, 185, 320]}
df = pd.DataFrame(data=d)
df = df.sort_values(by='linear')
df['ratings'] = 1,2,2,3,3,4,5,5
df
Подскажите, пожалуйста, каким способом можно автоматизировать процесс расставления этих рейтингов?
Ответы (1 шт):
Если у вас нужные значения отсортированы, и вам просто нужно разбить их на квантильные сегменты, то сделать это можно просто:
df["cat"] = pd.qcut(df["linear"], 6, labels=False).values+1
df:
stores linear cat
2 AG85 120 1
14 AH32 125 1
1 AG41 145 1
3 AG45 180 2
13 AD11 190 2
4 AG31 250 2
5 AS25 250 2
6 AR81 250 2
7 AA43 320 4
12 AT58 350 4
8 AG21 376 4
9 AD83 390 5
15 AE17 390 5
10 AA36 420 6
0 AG21 430 6
11 AG55 580 6
Если у вас нет каких-то категорий (как 3 в данном примере), значит ни одно из значений при данных условиях не попадает в третью секстиль. Если вам нужно железно получить 6 категорий, то тогда предлагаю сначала самостоятельно определить интервалы, а потом восользоваться методом pd.cut:
intervals = np.linspace(df["linear"].min(), df["linear"].max(), endpoint=True, num=7)
print(intervals) # [120. 196.66666667 273.33333333 350. 426.66666667 503.33333333 580. ]
df["cat"] = pd.cut(df["linear"], intervals, labels=False, include_lowest=True)+1
df:
stores linear cat
2 AG85 120 1
14 AH32 125 1
1 AG41 145 1
3 AG45 180 1
13 AD11 190 1
4 AG31 250 2
5 AS25 250 2
6 AR81 250 2
7 AA43 320 3
12 AT58 350 3
8 AG21 376 4
9 AD83 390 4
15 AE17 390 4
10 AA36 420 4
0 AG21 430 5
11 AG55 580 6
UPDATE
Если нужно поделить датафрейм просто на приблизительно равные части, ***с потерей статистической значимости***, можно сделать простую группировку:
d = {'stores': ['AG21', 'AG41', 'AG85', 'AG45', 'AG31', 'AS25', 'AR81', 'AA43'], 'linear': [330, 145 , 120, 180, 250, 150, 185, 320]}
df = pd.DataFrame(data=d)
df = df.sort_values(by='linear')
chunks = 6
df["cat"] = df.groupby(np.arange(len(df))//(len(df)/chunks)).ngroup()+1
print(df)
df:
stores linear cat
2 AG85 120 1
1 AG41 145 1
5 AS25 150 2
3 AG45 180 3
6 AR81 185 4
4 AG31 250 4
7 AA43 320 5
0 AG21 330 6