Как создать иерархическую таблицу содержания, такую ​​как индекс с пандами? - PullRequest
3 голосов
/ 24 сентября 2019

Предположим, у меня есть DataFrame следующей структуры:

df = pd.DataFrame(
    { 
        'Heading 1': ['Cat 1'] * 5 + ['Cat 2'] * 5 + ['Cat 3'] * 5, 
        'Heading 2': ['Group 1'] * 2 + ['Group 2'] * 2 + [''] + ['Group 1'] * 2 + [''] * 2 + ['Group 2'] + [''] + ['Group 1', 'Group 2', 'Group 3', 'Group 3'],
        'Heading 3': [f'Case {i}' for i in range(1, 6)] * 3
    }
)

, которая выглядит следующим образом (фактические данные не содержат цифр в конце, это только для иллюстрации):

# Source Data 

   Heading 1 Heading 2 Heading 3
0      Cat 1   Group 1    Case 1
1      Cat 1   Group 1    Case 2
2      Cat 1   Group 2    Case 3
3      Cat 1   Group 2    Case 4
4      Cat 1              Case 5
5      Cat 2   Group 1    Case 1
6      Cat 2   Group 1    Case 2
7      Cat 2              Case 3
8      Cat 2              Case 4
9      Cat 2   Group 2    Case 5
10     Cat 3              Case 1
11     Cat 3   Group 1    Case 2
12     Cat 3   Group 2    Case 3
13     Cat 3   Group 3    Case 4
14     Cat 3   Group 3    Case 5

Я хочу создать новый столбец, который будет представлять иерархию этих столбцов, чтобы он выглядел следующим образом:

# Desired Data

   Heading 1 Heading 2 Heading 3 Indexed
0      Cat 1   Group 1    Case 1   1.1.1    
1      Cat 1   Group 1    Case 2   1.1.2
2      Cat 1   Group 2    Case 3   1.2.1
3      Cat 1   Group 2    Case 4   1.2.2
4      Cat 1              Case 5     1.3
5      Cat 2   Group 1    Case 1   2.1.1
6      Cat 2   Group 1    Case 2   2.1.2
7      Cat 2              Case 3     2.2
8      Cat 2              Case 4     2.3
9      Cat 2   Group 2    Case 5   2.4.1
10     Cat 3              Case 1     3.1
11     Cat 3   Group 1    Case 2   3.2.1
12     Cat 3   Group 2    Case 3   3.3.1
13     Cat 3   Group 3    Case 4   3.4.1
14     Cat 3   Group 3    Case 5   3.4.2

Как этого достичь?Я могу индексировать его по заголовкам 1 и 2, пробовал df.set_index(list(df.columns)[:-1]).groupby(level=1).cumcount(), основываясь на моем понимании этого ответа , структура выглядит как нечто, что я могу использовать для построения "проиндексированного" столбца, но я изо всех силчтобы получить правильные числа:

# Some sort of in between state...

Heading 1  Heading 2
Cat 1      Group 1      0
           Group 1      1
           Group 2      0
           Group 2      1
                        0
Cat 2      Group 1      2
           Group 1      3
                        1
                        2
           Group 2      2
Cat 3                   3
           Group 1      4
           Group 2      3
           Group 3      0
           Group 3      1

Я знаю, что могу сделать apply с пользовательской функцией, чтобы сделать это, но есть ли встроенный метод pandas, которого мне здесь не хватает?

Редактировать: Для ясности мои фактические данные не содержат цифр и выглядят примерно так:

# Closer to actual data

             Main  Group    Case
0      Some Topic  Dummy  Case A
1      Some Topic  Dummy  Case B
2      Some Topic   Test  Case C
3      Some Topic   Test  Case D
4      Some Topic         Case E
5      Diff Topic    Foo  Case A
6      Diff Topic    Foo  Case B
7      Diff Topic         Case C
8      Diff Topic         Case D
9      Diff Topic    Bar  Case E
10  Another Topic         Case A
11  Another Topic    Baz  Case B
12  Another Topic    Uno  Case C
13  Another Topic    Dos  Case D
14  Another Topic   Tres  Case E

1 Ответ

2 голосов
/ 24 сентября 2019

Это можно сделать с помощью shift создать подгруппу, тогда нам просто нужно объединить их

s1=df.mask(df=='').groupby(['Heading 1'])['Heading 2'].apply(lambda x : (x!=x.shift()).cumsum()).astype(str)
s2=df.groupby(['Heading 1','Heading 2']).cumcount().add(1).astype(str)
s=df['Heading 1'].str.split(' ').str[1]+'.'+s1+'.'+s2.mask(df['Heading 2']=='','')
s=s.str.strip('.')
s
Out[256]: 
0     1.1.1
1     1.1.2
2     1.2.1
3     1.2.2
4       1.3
5     2.1.1
6     2.1.2
7       2.2
8       2.3
9     2.4.1
10      3.1
11    3.2.1
12    3.3.1
13    3.4.1
14    3.4.2
dtype: object
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...