Я использую массовые данные (Список действительных символов 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, чтобы показать желаемый результат первых нескольких строк:
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.
Обновлено: мне нужно лучше объяснить, как определить родителя узла. Значение уровня и позиция строки — это все, что необходимо для определения родителя.
Я хотел бы использовать pandas для выполнения работы, но я не уверен, с чего начать. Есть берущие? Спасибо
@Supratim Haldar, я понимаю, что вы имеете в виду, родителем индекса 5 является индекс 4. Индекс 5 - это уровень 8, а индекс 4 - это уровень 7. На самом деле не имеет значения, какой символ, единственное, что имеет значение, это уровень и положение строки для определения иерархии.
Может быть, это только я, но логика определения родителя не ясна. Я думал, что первая часть symbol
определяет родителя (например, «A01B» является родителем «A01B 1/00»). Но вы упомянули, что символ не имеет значения. Не могли бы вы четко объяснить логику и обновить свой вопрос?
@SupratimHaldar Я добавил диаграмму, показывающую иерархию. надеюсь это поможет.
Как насчет загрузки предварительно связанные данные и последующего анализа с помощью rdflib?
хм, не уверен. У вас есть код, чтобы показать?
В этом ответе я предполагаю, что ваш прямой родитель всегда находится в строке выше вашего собственного, поскольку это то, что предлагает ваш ожидаемый результат и ваша диаграмма.
С этой гипотезой мы можем для каждой строки взять ближайшую строку с уровнем ниже строки:
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.
я думаю, что-то вроде if len(potential_parents) == 0: df.loc[index, 'Parent'] = ''
может работать нормально.
Хорошая идея, я отредактировал свой ответ и проверил его на простом примере. Кажется, это работает
Я не думаю, что нам нужно первое утверждение if
. Просто проверьте длину potential_parents
и, если она равна 0, установите родителем этого символа значение ''
, иначе potential_parents.iloc[-1]
Есть ли способ ускорить генерацию potential_parents
? Может что-то, что смотрит в диапазоне только ряды первого выше уровня 2? Символы, начинающиеся с B, никогда не будут иметь родителя, начинающегося с A. Кроме того, символы уровня 19 будут иметь очень длинный список potent_parent
.
Вы можете думать об этом списке как о 8 отдельных деревьях... Что, если мы составим список индексов каждого символа уровня 2 и ограничим диапазон df, который мы ищем potential_parents
, этим списком?
Продолжим обсуждение в чате: chat.stackoverflow.com/rooms/194892/проблема уровня
Мы скучали друг по другу в чате. Вот моя идея: разбить df на sub-df на каждом уровне 2. Запустите приведенный выше код, чтобы получить родителей, а затем объедините каждый sub-df
Вот еще один метод. 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. Можете ли вы объяснить значения в иерархии и как бы я изменил их для обработки всего файла?
Ладно, разобрался. Это решение во много раз быстрее. Спасибо! hierarchy = [0, 0, 0, 0, 2, 4, 0, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
parent = [' ']*20
«строка 5 (A01B 1/02) будет иметь значение индекса 4 для значения в родительском столбце», но родитель строки 5 имеет индекс 3. Не так ли?