Объедините несколько категорий в одну в Pandas - PullRequest
3 голосов
/ 29 октября 2019

У меня есть набор данных со столбцом, который содержит категории. Я хотел бы объединить эти категории в новые категории.

Мой набор данных выглядит следующим образом (столбец категорий представляет собой строковый столбец), и у меня есть 160 категорий.

Нижев моем примере показаны только четыре категории.

Category  
ZA-01
ZA-01
ZA-01
ZA-01
XA-01
XA-01
XA-01
XA-01
YA-01
YA-01
YA-01
YA-01
WA-01
WA-01
WA-01
WA-01

Я хотел бы получить следующее (при неизменном исходном порядке строк в кадре данных это очень важно)

Category     New_Category
ZA-01        A
ZA-01        A
ZA-01        A
ZA-01        A
XA-01        A
XA-01        A
XA-01        A
XA-01        A
YA-01        B
YA-01        B
YA-01        B
YA-01        B
WA-01        B
WA-01        B
WA-01        B
WA-01        B

Самый простой способ сделать это - использовать оператор if elif, но если у вас около 160 категорий, это сложная задача, и она может легко пойти не так.

Что бы я хотелкак в Python, это взять уникальные категории с помощью df. [['Categories]]. unique (), который сохраняет порядок категорий в кадре данных, а затем сказать Python: группа категорий одна (ZA-01) и две (XA-01) в новый с именем A, затем сгруппируйте три категории (YA-01) и четыре (WA-01) в новый с именем B и т. Д.

Есть ли способ сделать это в Python безиспользуя if elif statemEnt?


------------------ Редактировать -----------------------

Что если бы у меня было

Group    Category  
A        ZA-01
A        ZA-01
A        ZA-01
A        ZA-01
A        XA-01
A        XA-01
A        XA-01
A        XA-01
A        ZZ-12      
A        ZX-11      
B        YA-01
B        YA-01
B        YA-01
B        YA-01
B        WA-01
B        WA-01
B        WA-01
B        WA-01
B        ZZ-01      
B        ZZ-99      
B        ZZ-99      
B        AA-01 

И я хотел объединить категории из двух в группе (поэтому в ИИ хотят объединить группы из двух категорий, а в BI хотят объединить две категориии так далее). Опять же, я хочу сохранить порядок строк в исходном фрейме данных.

Поэтому я хочу получить

Group    Category   New_Category
A        ZA-01      1
A        ZA-01      1
A        ZA-01      1
A        ZA-01      1
A        XA-01      1
A        XA-01      1
A        XA-01      1
A        XA-01      1
A        ZZ-12      2
A        ZX-11      2   
B        YA-01      3
B        YA-01      3
B        YA-01      3
B        YA-01      3
B        WA-01      3
B        WA-01      3
B        WA-01      3
B        WA-01      3
B        ZZ-01      4
B        ZZ-99      4
B        ZZ-99      4
B        AA-01      5

Ответы [ 2 ]

5 голосов
/ 29 октября 2019

Для исправленного вопроса :

Группе не нужно. Просто используйте factorize с кортежем Group и Category

df['New_Category']= (pd.factorize(list(zip(df.Group, df.Category)))[0] // 2) + 1

Out[272]:
   Group Category  New_Category
0      A    ZA-01             1
1      A    ZA-01             1
2      A    ZA-01             1
3      A    ZA-01             1
4      A    XA-01             1
5      A    XA-01             1
6      A    XA-01             1
7      A    XA-01             1
8      A    ZZ-12             2
9      A    ZX-11             2
10     B    YA-01             3
11     B    YA-01             3
12     B    YA-01             3
13     B    YA-01             3
14     B    WA-01             3
15     B    WA-01             3
16     B    WA-01             3
17     B    WA-01             3
18     B    ZZ-01             4
19     B    ZZ-99             4
20     B    ZZ-99             4
21     B    AA-01             5

Оригинал :

Используйте pd.factorize и этаж div 2

df['new_category'] = pd.factorize(df.Category)[0] // 2

Out[154]:
   Category  new_category
0     ZA-01             0
1     ZA-01             0
2     ZA-01             0
3     ZA-01             0
4     XA-01             0
5     XA-01             0
6     XA-01             0
7     XA-01             0
8     YA-01             1
9     YA-01             1
10    YA-01             1
11    YA-01             1
12    WA-01             1
13    WA-01             1
14    WA-01             1
15    WA-01             1

После добавления new_category выше, если вы хотите сопоставить свои пользовательские категории, просто выполните эти дополнительные шаги

cats = np.array(['A', 'B'])
df['new_category'] = cats[df['new_category']]

Out[163]:
   Category new_category
0     ZA-01            A
1     ZA-01            A
2     ZA-01            A
3     ZA-01            A
4     XA-01            A
5     XA-01            A
6     XA-01            A
7     XA-01            A
8     YA-01            B
9     YA-01            B
10    YA-01            B
11    YA-01            B
12    WA-01            B
13    WA-01            B
14    WA-01            B
15    WA-01            B

Добавьте метод @piRSquare ofсоздавать алфавитные категории

from string import ascii_uppercase
from itertools import product
import numpy as np

letters = [*ascii_uppercase]
leading = [''] + letters
cats = np.array([*map(''.join, product(*[leading] * 3, letters))])

или

from string import ascii_uppercase
from itertools import product
cats = np.array([*map(''.join, product(['', *ascii_uppercase], ascii_uppercase))])
cats[df.Category.factorize()[0] // 2]

Out[13]:
array(['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B',
       'B', 'B', 'B'], dtype='<U2')
4 голосов
/ 29 октября 2019

Вы можете сделать, как вы сказали, с map:

cats = df.Category.unique()

# define new categories
# replace np.arange(len(cats)) with your category names
# e.g ['A','B']
new_cats = np.repeat(np.arange(len(cats)), 2)[:len(cats)]

s = pd.Series(new_cats, index=cats)
df['New_Cat'] = df['Category'].map(s)

Вывод:

   Category  New_Cat
0     ZA-01        0
1     ZA-01        0
2     ZA-01        0
3     ZA-01        0
4     XA-01        0
5     XA-01        0
6     XA-01        0
7     XA-01        0
8     YA-01        1
9     YA-01        1
10    YA-01        1
11    YA-01        1
12    WA-01        1
13    WA-01        1
14    WA-01        1
15    WA-01        1

Detail : s is

ZA-01    0
XA-01    0
YA-01    1
WA-01    1
dtype: int32
...