Панды уменьшают количество категориальных переменных в таблице value_counts()

Новичок в пандах. Я хочу выполнить что-то похожее на Уменьшите количество уровней для больших категориальных переменных (объединение категориальных переменных для уменьшения их уровней) Следующий код отлично работает в R

DTsetlvls <- function(x, newl)  
   setattr(x, "levels", c(setdiff(levels(x), newl), rep("other", length(newl))))

Мой фрейм данных:

df = pd.DataFrame({'Color': 'Red Red Blue'.split(),
                   'Value': [100, 150, 50]})

df['Counts'] = df.groupby('Color')['Value'].transform('count')
print (df)

  Color  Value  Counts
0   Red    100       2
1   Red    150       2
2  Blue     50       1

Я бы вручную создал совокупный столбец, а затем на его основе пометил менее частые группы, например. «синий» как единая «другая» группа. Но по сравнению с кратким кодом R это кажется неуклюжим. Какой подход здесь будет правильным?


person Georg Heiler    schedule 23.08.2016    source источник
comment
Возможный дубликат Как сгруппировать оставшиеся результаты за пределами Top N в Others с пандами   -  person Ami Tavory    schedule 23.08.2016


Ответы (1)


Вы можете использовать value_counts с numpy.where, где условие с isin.

Если ваша переменная имеет тип object, см. ниже. Если ваша переменная относится к категории типов, пропустите ее вниз.

df = pd.DataFrame({'Color':'Red Red Blue Red Violet Blue'.split(), 
                   'Value':[11,150,50,30,10,40]})
print (df)
    Color  Value
0     Red     11
1     Red    150
2    Blue     50
3     Red     30
4  Violet     10
5    Blue     40

a = df.Color.value_counts()
print (a)
Red       3
Blue      2
Violet    1
Name: Color, dtype: int64

#get top 2 values of index
vals = a[:2].index
print (vals)
Index(['Red', 'Blue'], dtype='object')

df['new'] = np.where(df.Color.isin(vals), 0,1)
print (df)
    Color  Value  new
0     Red     11    0
1     Red    150    0
2    Blue     50    0
3     Red     30    0
4  Violet     10    1
5    Blue     40    0

Или, если нужно заменить все не верхние значения, используйте where:

df['new1'] = df.Color.where(df.Color.isin(vals), 'other')
print (df)
    Color  Value   new1
0     Red     11    Red
1     Red    150    Red
2    Blue     50   Blue
3     Red     30    Red
4  Violet     10  other
5    Blue     40   Blue

Для типа категории:

df = pd.DataFrame({'Color':'Red Red Blue Red Violet Blue'.split(), 
                   'Value':[11,150,50,30,10,40]})
df.Color = df.Color.astype('category')

a= df.Color.value_counts()[:2].index
print(a)
CategoricalIndex(['Red', 'Blue'], 
                categories=['Blue', 'Red', 'Violet'], 
                ordered=False, dtype='category')

Обратите внимание, что фиолетовый по-прежнему является категорией. Итак, нам нужен .remove_unused_categories().

vals = df.Color.value_counts()[:2].index.remove_unused_categories()
CategoricalIndex(['Red', 'Blue'], 
                 categories=['Blue', 'Red'], 
                 ordered=False, dtype='category')

Как упоминалось в комментариях, при установке новой переменной произойдет ValueError. Обойти это изменением типа.

df['new1'] = df.Color.astype('object').where(df.Color.isin(vals), 'other')
df['new1'] = df['new1'].astype('category')
person jezrael    schedule 23.08.2016
comment
Я получаю эту ошибку ValueError: Cannot setitem on a Categorical with a new category, set the categories first. Это связано с тем, что моя переменная уже является категоричной. Мое исправление заключалось в добавлении .astype('object') вот так df.Color.astype('object').where(df.Color.isin(vals), 'other'). - person Climbs_lika_Spyder; 20.05.2020