Как создать категориальную переменную на основе числовой переменной

Мой DataFrame имеет один столбец:

import pandas as pd
list=[1,1,4,5,6,6,30,20,80,90]
df=pd.DataFrame({'col1':list})

Как я могу добавить еще один столбец «col2», который будет содержать категориальную информацию со ссылкой на col1:

if col1 > 0 and col1 <= 10 then col2 = 'xxx'
if col1 > 10 and col1 <= 50 then col2 = 'yyy'
if col1 > 50 then col2 = 'zzz'

person Klausos Klausos    schedule 17.09.2015    source источник


Ответы (3)


Вы можете сначала создать новый столбец col2 и обновить его значения в зависимости от условий:

df['col2'] = 'zzz'
df.loc[(df['col1'] > 0) & (df['col1'] <= 10), 'col2'] = 'xxx'
df.loc[(df['col1'] > 10) & (df['col1'] <= 50), 'col2'] = 'yyy'
print df

Выход:

   col1 col2
0     1  xxx
1     1  xxx
2     4  xxx
3     5  xxx
4     6  xxx
5     6  xxx
6    30  yyy
7    20  yyy
8    80  zzz
9    90  zzz

Кроме того, вы также можете применить функцию на основе столбца col1:

def func(x):
    if 0 < x <= 10:
        return 'xxx'
    elif 10 < x <= 50:
        return 'yyy'
    return 'zzz'

df['col2'] = df['col1'].apply(func)

и это приведет к тому же результату.

В этом случае следует отдать предпочтение подходу apply, так как он намного быстрее:

%timeit run() # packaged to run the first approach
# 100 loops, best of 3: 3.28 ms per loop
%timeit df['col2'] = df['col1'].apply(func)
# 10000 loops, best of 3: 187 µs per loop

Однако, когда размер DataFrame велик, встроенные векторизованные операции (т. е. с подходом маскирования) могут быть быстрее.

person YS-L    schedule 17.09.2015

Вы можете использовать pd.cut следующим образом:

df['col2'] = pd.cut(df['col1'], bins=[0, 10, 50, float('Inf')], labels=['xxx', 'yyy', 'zzz'])

Выход:

   col1 col2
0     1  xxx
1     1  xxx
2     4  xxx
3     5  xxx
4     6  xxx
5     6  xxx
6    30  yyy
7    20  yyy
8    80  zzz
9    90  zzz
person DontDivideByZero    schedule 11.10.2017
comment
Это гораздо более приятное решение, чем другие ответы, спасибо! - person MokeEire; 23.06.2018
comment
В документах даже говорится, что используйте cut, когда вам нужно сегментировать и сортировать значения данных по ячейкам. - person Fush; 19.06.2019

2 способа, используйте пару вызовов loc, чтобы замаскировать строки, в которых выполняются условия:

In [309]:
df.loc[(df['col1'] > 0) & (df['col1']<= 10), 'col2'] = 'xxx'
df.loc[(df['col1'] > 10) & (df['col1']<= 50), 'col2'] = 'yyy'
df.loc[df['col1'] > 50, 'col2'] = 'zzz'
df

Out[309]:
   col1 col2
0     1  xxx
1     1  xxx
2     4  xxx
3     5  xxx
4     6  xxx
5     6  xxx
6    30  yyy
7    20  yyy
8    80  zzz
9    90  zzz

Или используйте вложенный np.where:

In [310]:
df['col2'] = np.where((df['col1'] > 0) & (df['col1']<= 10), 'xxx', np.where((df['col1'] > 10) & (df['col1']<= 50), 'yyy', 'zzz'))
df

Out[310]:
   col1 col2
0     1  xxx
1     1  xxx
2     4  xxx
3     5  xxx
4     6  xxx
5     6  xxx
6    30  yyy
7    20  yyy
8    80  zzz
9    90  zzz
person EdChum    schedule 17.09.2015