在由成对的项目组成的约50万行的列表中,我试图建立一个文件,旨在为每个项目分配一个与它们所属的组相关的ID。进一步的解释如下。

而且,我需要一些帮助,以一种聪明高效的方式来获得结果(即pythonic)

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

我想做的事

将输入文件df0转换为所需的输出df2

例如,起始文件看起来像这样(但有500k条目),其中从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.items返回df1.group

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步并直接从df1中获得df2的更好方法


非常感谢您的时间和反馈!

最佳答案

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

关于python - 如何为共享评论元素的子列表的每个元素赋予相关子列表的唯一ID?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55511992/

10-12 00:30
查看更多