Как приписать каждому элементу подсписка, разделяющего элементы комментариев, уникальный идентификатор связанного подсписка?

#python #pandas #performance #networkx #subgraph

#python #pandas #Производительность #networkx #подграф

Вопрос:

Из списка из ~ 500 тысяч строк, состоящего из пар элементов, я пытаюсь создать файл, целью которого является выделение для каждого элемента идентификатора, связанного с группой, к которой они принадлежат. Далее следуют пояснения.

И мне понадобится некоторая помощь, чтобы получить результат разумным и эффективным способом (то есть pythonic)

==============

что я хочу сделать

Преобразуйте входной файл df0 в желаемый результат df2

Например, начальный файл будет выглядеть следующим образом (но с 500 тысячами записей), где отношение от item1 к item2 определяется структурой фрейма данных.

df0: ввод

 df0 = pd.DataFrame({
"item 1": ['Q', 'R', 'B', 'A'],
"item 2": ['R', 'P', 'A', 'C']
})
  

Он читается следующим образом: элемент Q связан с элементом R, а элемент R связан с элементом P, следовательно, элемент Q связан с элементом P (то же самое с С A, B и C). В этом случае транзитивность отношений приводит к созданию двух групп элементов.

  • Каждый элемент принадлежит только к 1 группе.
  • Ожидается, что в реальном файле примера группы могут содержать до 11 элементов.
  • алфавитный порядок не играет роли

Благодаря другим вкладам в stackoverflow мне удалось сгруппировать все транзитивные элементы в отдельные наборы и присвоить им единый номер группы (или ID). Это означает, что я получаю фрейм данных, который выглядит следующим образом:

 df1 = pd.DataFrame({
"items": [{'Q', 'R', 'P'}, {'B', 'A', 'C'} ],
"group": [1, 2]
})
  

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

df2: желаемый результат

 df2 = pd.DataFrame({
"items": ['Q', 'R', 'P', 'B', 'A', 'C' ],
"group": [1, 1, 1, 2, 2, 2 ]
})
  

==============

Что мне удалось до сих пор

шаг 1: преобразуйте df1.item в серию отдельных элементов

 d = df1.item
e = list(sorted(set(chain.from_iterable(d))))
df2 = pd.DataFrame({'item':e})
  

шаг 2: ‘vlookup’ df2.items возвращается в df1.group через df1.items

 df2['group'] = ''  

n = 0
for row in df2.items :
m = 0
for row in df1.items :
    if df2['items'][n] in df1['items'][m]:
        df2['group'][n] = df1['group'][m]
    m = m   1
n = n   1
  

==============

Это работает для небольших таблиц, но не работает на больших фреймах данных.

Сейчас я ищу помощь относительно :

  • либо лучший код для шага 2 для улучшения df2 (предпочтительно)
  • или лучший способ перепрыгнуть через шаг 2 и получить df2 прямо из df1

Заранее благодарю вас за ваше время и обратную связь!

Комментарии:

1. 1) R Связано с B ? 2) Почему вы хотите использовать фреймы данных?

2. 1) согласно df0, R не связан с B. Иначе у нас была бы только одна группа. 2) У меня нет ограничений не использовать фреймы данных, я открыт для альтернатив.

Ответ №1:

IIUC, вы могли бы попробовать заглянуть в networkx библиотеку.

Вы можете создать непрямый сетевой график непосредственно из своего pandas.DataFrame и использовать connected_component_subgraphs метод для извлечения подгрупп:

 import networkx as nx

df0 = pd.DataFrame({'item 1': {0: 'Q', 1: 'R', 2: 'B', 3: 'A'},
                    'item 2': {0: 'R', 1: 'P', 2: 'A', 3: 'C'}})

g = nx.convert_matrix.from_pandas_edgelist(df0, source='item 1', target='item 2')
  

Используйте понимание списка для создания данных для вашего нового DataFrame

 subgroups = [(n, i   1) for i, sg in enumerate(nx.connected_component_subgraphs(g)) for n in sg.nodes]

df2 = pd.DataFrame(subgroups, columns=['items', 'subgroup'])
print(df2)

  items  subgroup
0     P         1
1     R         1
2     Q         1
3     C         2
4     A         2
5     B         2
  

Комментарии:

1. потрясающе Я только что протестировал в Jupyter файл размером ~ 400 тыс. строк, и он отлично сработал! большое вам спасибо!

2. @ionah рад помочь 🙂