使用稀疏矩阵时,如何保存额外的列信息?

问题描述 投票:1回答:1

我试图找出在使用稀疏矩阵时如何保存额外的信息。我正在写一些代码,将pandas数据框变成网络。数据框有一列节点,一列边,还有一些属性列。

>>> df.head()

  authors  papers     attr1             attr2
0       g  [4, 8]  yikpmrbf  FCCLYDWSFJVORGXL
1       h     [7]  zxdkzyam  DHJZADCAPRQYAXGR
2       c     [4]  lnynqqhf  PACVSZULQSKXBURW
3       k  [5, 3]  vjzgyebn  QMLHUIDWXGNPVQTH
4       r     [7]  etjghgcp  CSYIMFXKOYFWWUTH

到目前为止,我一直在使用下面的代码来制作一个网络x图,其中包括 authors 是指在以下情况下具有边的节点,如果它们在 papers.

from itertools import chain
import numpy as np
from scipy import sparse
import networkx as nx

node='authors'
link='papers'

indptr = np.fromiter(chain((0,), map(len, df[link])),
                     int, len(df[link])+1).cumsum()
unq, idx = np.unique(np.concatenate(df[link]), return_inverse=True)
node_link_matrix = sparse.csr_matrix(
    (np.ones(idx.size, int), idx, indptr),
    (len(df[link]),
     len(unq))
)
node_node_matrix = (node_link_matrix@node_link_matrix.T).tocoo()
G = nx.convert_matrix.from_scipy_sparse_matrix(node_node_matrix)

这将计算数据中每个节点对的边缘权重。node_link_matrix 在数据框架中,有多少行就有多少列,有多少列就有多少个唯一的边缘值(这里是唯一的论文)。因此,这些值表示 "x行中有多少x篇论文"。node_node_matrix 是正方形,数据框中的行数有多少列就有多少列。它是下列各项的点乘 node_link_matrixnode_link_matrix 转置。这些值是边缘权重,这个矩阵可以很容易地变成一个有网络x的图。

>>> node_link_matrix
<74x10 sparse matrix of type '<class 'numpy.int64'>'
    with 140 stored elements in Compressed Sparse Row format>

>>> node_node_matrix
<74x74 sparse matrix of type '<class 'numpy.int64'>'
    with 1786 stored elements in COOrdinate format>

我想得到的是关于 attr1 列变成这样。我先试着把 "那些 "替换成实际的属性字符串,所以前面的代码就变成了。

from itertools import chain
import numpy as np
from scipy import sparse
import networkx as nx

node='authors'
link='papers'

indptr = np.fromiter(chain((0,), map(len, df[link])),
                     int, len(df[link])+1).cumsum()
unq, idx = np.unique(np.concatenate(df[link]), return_inverse=True)
node_link_matrix = sparse.csr_matrix(
    (np.repeat(df.attr1.values, np.diff(indptr)), idx, indptr),  # <-- Changed this part
    (len(df[link]),
     len(unq))
)

这行不通,因为稀疏矩阵不能很好地处理字符串。我试着用一个字典来代替实际值,将每个出现的值映射到正确的属性上,来克服这个问题。

from itertools import chain
import numpy as np
from scipy import sparse
import networkx as nx

node='authors'
link='papers'

indptr = np.fromiter(chain((0,), map(len, df[link])),
                     int, len(df[link])+1).cumsum()
unq, idx = np.unique(np.concatenate(df[link]), return_inverse=True)
node_link_matrix = sparse.csr_matrix(
    (range(idx.size), idx, indptr),  # <-- Values are now IDs
    (len(df[link]),
     len(unq))
)

edge_attr_dict = dict(zip(range(idx.size), np.repeat(df.attr1.values, np.diff(indptr))))

那么,这就给了我一个 node_link_matrix 将节点值映射到边缘值及其对应的attr1值。问题是,由于现在的值都是符号数,而不仅仅是1和0,所以用点积函数来获取节点与节点之间的关系就不能用了。所以我需要的是一种方法,既能保留稀疏矩阵中的节点属性信息,又能如愿以偿地使用点积函数。我一直在考虑是否可以通过将属性信息 "推 "到第三维度,使用三维张量而不是稀疏矩阵来实现,但我没有太多这方面的经验。

python scipy networkx sparse-matrix tensor
1个回答
1
投票

这里有一个相当快速的方法来重新处理你的表,这是 Node 1 -Node 2 - Edge attributes.

edges = []

for p, group in df.explode("papers").groupby("papers"):

    # Add a new author2 edge column and explode it
    authors = group["authors"].tolist()
    group = group.copy() # This explicit copy suppresses an implicit-copy warning
    group["author2"] = [authors for _ in range(group.shape[0])]
    group = group.explode("author2")

    # Get rid of self-interaction rows
    edges.append(group.loc[group["authors"] != group["author2"], :])

edges = pd.concat(edges)
edges.reset_index(drop=True, inplace=True)

这将比COO矩阵的内存更大,但只要你的数据不是非常大,拥有一个数据框架的灵活性是值得的。

© www.soinside.com 2019 - 2024. All rights reserved.