Добавление столбца в Dataframe, содержащего символ родительского узла

Я использую массовые данные (Список действительных символов CPC) из веб-сайт КТК. Я прочитал csv в pandas df, и первые 30 строк (более 260 КБ):

    SYMBOL  level   not-allocatable additional-only
1   A   2   True    False
2   A01 4   True    False
3   A01B    5   True    False
4   A01B 1/00   7   False   False
5   A01B 1/02   8   False   False
6   A01B 1/022  9   False   False
7   A01B 1/024  9   False   False
8   A01B 1/026  9   False   False
9   A01B 1/028  9   False   False
10  A01B 1/04   9   False   False
11  A01B 1/06   8   False   False
12  A01B 1/065  9   False   False
13  A01B 1/08   9   False   False
14  A01B 1/10   9   False   False
15  A01B 1/12   9   False   False
16  A01B 1/14   9   False   False
17  A01B 1/16   8   False   False
18  A01B 1/165  9   False   False
19  A01B 1/18   9   False   False
20  A01B 1/20   8   False   False
21  A01B 1/22   8   False   False
22  A01B 1/222  9   False   False
23  A01B 1/225  10  False   False
24  A01B 1/227  9   False   False
25  A01B 1/24   8   False   False
26  A01B 1/243  9   False   False
27  A01B 1/246  9   False   False
28  A01B 3/00   7   False   False
29  A01B 3/02   8   False   False

Значение уровня создает иерархию. Таким образом, узел A01B 1/00 ​​имеет уровень 7 и является потомком узла A01B. A01B 1/02 — это уровень 8, а потомок A01B 1/00 ​​и A01b 3/00 — потомок A01B.

Я хотел бы создать новый столбец с именем PARENT, который содержит SYMBOL прямого родителя узла. Например, я отредактировал csv в Excel, чтобы показать желаемый результат первых нескольких строк:

Добавление столбца в Dataframe, содержащего символ родительского узла

Note: there are no level 1, 3, or 6 symbols. There are multiple level 2 symbols. There is no parent for level 2 symbols, the parent of level 4 symbols can be assigned the first level 2 symbol above it, and the parent of level 7 symbols likewise can be assigned the first level 5 symbol above it.

Обновлено: мне нужно лучше объяснить, как определить родителя узла. Значение уровня и позиция строки — это все, что необходимо для определения родителя.Добавление столбца в Dataframe, содержащего символ родительского узла

Я хотел бы использовать pandas для выполнения работы, но я не уверен, с чего начать. Есть берущие? Спасибо

«строка 5 (A01B 1/02) будет иметь значение индекса 4 для значения в родительском столбце», но родитель строки 5 имеет индекс 3. Не так ли?

Supratim Haldar 29.05.2019 22:38

@Supratim Haldar, я понимаю, что вы имеете в виду, родителем индекса 5 является индекс 4. Индекс 5 - это уровень 8, а индекс 4 - это уровень 7. На самом деле не имеет значения, какой символ, единственное, что имеет значение, это уровень и положение строки для определения иерархии.

Britt 29.05.2019 23:19

Может быть, это только я, но логика определения родителя не ясна. Я думал, что первая часть symbol определяет родителя (например, «A01B» является родителем «A01B 1/00»). Но вы упомянули, что символ не имеет значения. Не могли бы вы четко объяснить логику и обновить свой вопрос?

Supratim Haldar 30.05.2019 08:16

@SupratimHaldar Я добавил диаграмму, показывающую иерархию. надеюсь это поможет.

Britt 30.05.2019 17:08

Как насчет загрузки предварительно связанные данные и последующего анализа с помощью rdflib?

cfort 12.06.2019 16:31

хм, не уверен. У вас есть код, чтобы показать?

Britt 12.06.2019 16:56
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
6
269
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

С этой гипотезой мы можем для каждой строки взять ближайшую строку с уровнем ниже строки:

import pandas as pd

data = {"Symbol":["A", "A01", "A01B", "A01B 1/00", "A01B 1/02", "A01B 1/022", "B"], "level":[2,4,5,7,8,9,2]}

df=pd.DataFrame(data=data)
df['Parent'] = ''

for index, row in df.iterrows():
    # We look at the potential parents
    potential_parents = df.loc[df.index.isin([x for x in range(index)]) & (df['level'] < row['level']), 'Symbol']
    # And we take the last one as our parent
    if len(potential_parents) == 0: 
        df.loc[index, 'Parent'] = ''
    else:
        df.loc[index, 'Parent'] = potential_parents.iloc[-1]

Выход :

       Symbol  level     Parent
0           A      2           
1         A01      4          A
2        A01B      5        A01
3   A01B 1/00      7       A01B
4   A01B 1/02      8  A01B 1/00
5  A01B 1/022      9  A01B 1/02
6           B      2           

Это почти работает, но как только обрабатывается следующий символ уровня 2, появляется ошибка IndexError: single positional indexer is out-of-bounds. Есть 8 символов уровня 2, и у них нет родителя. Код должен учитывать несколько символов уровня 2.

Britt 13.06.2019 16:21

я думаю, что-то вроде if len(potential_parents) == 0: df.loc[index, 'Parent'] = '' может работать нормально.

Britt 13.06.2019 16:22

Хорошая идея, я отредактировал свой ответ и проверил его на простом примере. Кажется, это работает

vlemaistre 13.06.2019 16:29

Я не думаю, что нам нужно первое утверждение if. Просто проверьте длину potential_parents и, если она равна 0, установите родителем этого символа значение '', иначе potential_parents.iloc[-1]

Britt 13.06.2019 16:32

Есть ли способ ускорить генерацию potential_parents? Может что-то, что смотрит в диапазоне только ряды первого выше уровня 2? Символы, начинающиеся с B, никогда не будут иметь родителя, начинающегося с A. Кроме того, символы уровня 19 будут иметь очень длинный список potent_parent.

Britt 13.06.2019 16:36

Вы можете думать об этом списке как о 8 отдельных деревьях... Что, если мы составим список индексов каждого символа уровня 2 и ограничим диапазон df, который мы ищем potential_parents, этим списком?

Britt 13.06.2019 16:41

Продолжим обсуждение в чате: chat.stackoverflow.com/rooms/194892/проблема уровня

vlemaistre 13.06.2019 16:48

Мы скучали друг по другу в чате. Вот моя идея: разбить df на sub-df на каждом уровне 2. Запустите приведенный выше код, чтобы получить родителей, а затем объедините каждый sub-df

Britt 13.06.2019 17:36
Ответ принят как подходящий

Вот еще один метод. GetParent() возвращает функцию, которая отслеживает самый последний символ для каждого уровня и возвращает родителя текущего уровня. Использование его в pandas.apply() создает столбец с родительскими символами.

def GetParent():
    #            0  1  2  3  4  5  6  7  8  9  10
    hierarchy = [0, 0, 0, 0, 2, 4, 0, 5, 7, 8, 9]
    parent = [' ']*11

    def func(row):
        #print(row)
        symbol,level = row[['SYMBOL', 'level']]

        parent_level = hierarchy[level]
        parent_symbol = parent[parent_level]

        parent[level] = symbol

        return pd.Series([parent_symbol], index=['parent'])

    return func

# create a column with the parents
parents = df.apply(GetParent(), axis=1)
df = pd.concat([df, parents], axis=1)

df

Выход:

    SYMBOL  level   na      ao      parent
0   A           2   True    False   
1   A01         4   True    False   A
2   A01B        5   True    False   A01
3   A01B 1/00   7   False   False   A01B
4   A01B 1/02   8   False   False   A01B 1/00
5   A01B 1/022  9   False   False   A01B 1/02
6   A01B 1/024  9   False   False   A01B 1/02
7   A01B 1/026  9   False   False   A01B 1/02
8   A01B 1/028  9   False   False   A01B 1/02
9   A01B 1/04   9   False   False   A01B 1/02
10  A01B 1/06   8   False   False   A01B 1/00
11  A01B 1/065  9   False   False   A01B 1/06
12  A01B 1/08   9   False   False   A01B 1/06
...

Интересно. Там символы самого высокого уровня - 19. Можете ли вы объяснить значения в иерархии и как бы я изменил их для обработки всего файла?

Britt 14.06.2019 16:10

Ладно, разобрался. Это решение во много раз быстрее. Спасибо! hierarchy = [0, 0, 0, 0, 2, 4, 0, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]parent = [' ']*20

Britt 14.06.2019 16:35

Другие вопросы по теме