Pandas:从邻接矩阵到一系列节点列表

Pandas: from adjacency matrix to series of node lists

我有,我认为这是一个非常普遍的问题。即,在节点列表的列表中重铸二分邻接矩阵。在 Pandas 中,这意味着从特定的 pd.DataFrame 格式转换为特定的 pd.Series 格式。

对于非离散数学人员,这看起来像以下转换:

来自

df = pd.DataFrame(columns=['item1','item2','item3'],
                  index=['foo','bar','qux'], 
                  data = [[1,1,0],[0,1,1],[0,0,0]])

看起来像

    item1   item2   item3
foo     1       1       0
bar     0       1       1
qux     0       0       0

srs = pd.Series([['item1','item2'],['item2','item3'],[]],index=['foo','bar','qux'])

看起来像

foo    [item1, item2]
bar    [item2, item3]
qux                []
dtype: object

我已经通过以下代码部分实现了这个目标:

df_1 = df.stack().reset_index()

srs = df_1.loc[df_1[0]==1].groupby('level_0')['level_1'].apply(list)

除了有点不可读之外,还存在一路上掉落的问题 qux

是否有到达所需结果的更短路径?

如果想避免通过 stackgroupby 进行重塑,可以使用列表理解将 0,1 转换为 DataFrame.astype 的布尔值,然后过滤列名称,最后一次它到 Series 构造函数:

print([list(df.columns[x]) for x in df.astype(bool).to_numpy()])
[['item1', 'item2'], ['item2', 'item3'], []]

s = pd.Series([list(df.columns[x]) for x in df.astype(bool).to_numpy()], index=df.index)
print(s)
foo    [item1, item2]
bar    [item2, item3]
qux                []
dtype: object

如果性能也很重要,请使用:

c = df.columns.to_numpy()
s = pd.Series([list(c[x]) for x in df.astype(bool).to_numpy()], index=df.index)

对每一行应用简单的列表理解 (axis=1) 是可行的。如果行中没有非零元素,将生成一个空列表。

df.apply(lambda row: [df.columns[i] for i, el in enumerate(row) if el], axis=1)

结果

foo    [item1, item2]
bar    [item2, item3]
qux                []
dtype: object