Как определить конечные узлы в данных упорядоченной нумерации (иерархической)? - PullRequest
1 голос
/ 14 мая 2019

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

Например, формат данных выглядит следующим образом:

class
'1'
'1.1'
'1.1.1'
'1.1.2'
'1.1.3'
'1.2'
'2'
'2.1'
'2.2'
'2.2.1'
'2.2.2'

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

Мой текущий подход заключается в разделении строки по периодам и расширении столбцов.Затем установить MultiIndex с результирующими столбцами и отсортировать индекс.Затем представлена ​​иерархическая структура, но я не уверен, существует ли быстрый способ определения листьев.Я ищу эффективное решение, которое уже существует, а не комплекс для цикла, который я, вероятно, способен сам кодировать.

Я нашел пакет на CRAN для языка R, называемый data.tree , которая имеет функцию 'isLeaf', которая, кажется, идеально подходит для моего случая использования, но я не могу найти подобное решение для Python.

Вот код для достижения того, что яуже сделано:

import pandas as pd
my_dict = {1: '0',
 2: '1',
 3: '1.1',
 4: '01.1.1',
 5: '01.1.2',
 6: '01.1.3',
 7: '01.1.4',
 8: '01.1.5',
 9: '01.1.6',
 10: '01.1.7',
 11: '01.1.8',
 12: '01.1.9',
 13: '1.2',
 14: '01.2.1',
 15: '01.2.2',
 16: '2',
 17: '2.1',
 18: '02.1.1',
 19: '02.1.2',
 20: '02.1.3',
 21: '2.2',
 22: '3',
 23: '3.1',
 24: '03.1.2',
 25: '03.1.3',
 26: '03.1.4',
 27: '3.2',
 28: '4',
 29: '4.1',
 30: '4.2'}
# Create Series from Dictionary
class_df = pd.Series(my_dict)
class_df.name = 'class'
# Split column on period and concatenate to DataFrame
class_df = pd.concat([class_df, class_df.str.split('.', expand=True)], axis=1)
# Name columns
cols = ['class', 'level_1', 'level_2', 'level_3']
class_df.columns = cols
level_cols = cols[1:]
#Standardise formate by padding zeros
class_df['level_1'] = class_df['level_1'].str.pad(width=2, side='left', fillchar='0')
# String split creates None values so drop those.
class_df = class_df.fillna('').set_index(level_cols)
class_df = class_df.sort_index()

Вот как выглядит вывод в виде словаря и напечатанного фрейма данных.

{('00', '', ''): '0',
 ('01', '', ''): '1',
 ('01', '1', ''): '1.1',
 ('01', '1', '1'): '01.1.1',
 ('01', '1', '2'): '01.1.2',
 ('01', '1', '3'): '01.1.3',
 ('01', '1', '4'): '01.1.4',
 ('01', '1', '5'): '01.1.5',
 ('01', '1', '6'): '01.1.6',
 ('01', '1', '7'): '01.1.7',
 ('01', '1', '8'): '01.1.8',
 ('01', '1', '9'): '01.1.9',
 ('01', '2', ''): '1.2',
 ('01', '2', '1'): '01.2.1',
 ('01', '2', '2'): '01.2.2',
 ('02', '', ''): '2',
 ('02', '1', ''): '2.1',
 ('02', '1', '1'): '02.1.1',
 ('02', '1', '2'): '02.1.2',
 ('02', '1', '3'): '02.1.3',
 ('02', '2', ''): '2.2',
 ('03', '', ''): '3',
 ('03', '1', ''): '3.1',
 ('03', '1', '2'): '03.1.2',
 ('03', '1', '3'): '03.1.3',
 ('03', '1', '4'): '03.1.4',
 ('03', '2', ''): '3.2',
 ('04', '', ''): '4',
 ('04', '1', ''): '4.1',
 ('04', '2', ''): '4.2'}

                          class
level_1 level_2 level_3        
00                            0
01                            1
        1                   1.1
                1        01.1.1
                2        01.1.2
                3        01.1.3
                4        01.1.4
                5        01.1.5
                6        01.1.6
                7        01.1.7
                8        01.1.8
                9        01.1.9
        2                   1.2
                1        01.2.1
                2        01.2.2
02                            2
        1                   2.1
                1        02.1.1
                2        02.1.2
                3        02.1.3
        2                   2.2
03                            3
        1                   3.1
                2        03.1.2
                3        03.1.3
                4        03.1.4
        2                   3.2
04                            4
        1                   4.1
        2                   4.2

Ожидаемый вывод - я хочу вернуть логическое значениеРяды с True для строк, которые являются листьями в иерархическом дереве, и False в противном случае.

Оцените помощь.

...