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

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

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

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

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

Преобразовать входной файл 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 Ответ

3 голосов
/ 04 апреля 2019

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
...