【问题标题】:python: can I have a sparse matrix representation without (explicitly) using integer indices?python:我可以在不(明确)使用整数索引的情况下进行稀疏矩阵表示吗?
【发布时间】:2016-02-10 14:02:03
【问题描述】:

我有一个数据集,它本质上是一个稀疏二进制矩阵,表示两组元素之间的关系。例如,让第一组是人(用他们的名字表示),例如有点像这样:

people = set(['john','jane','mike','joe'])

第二组是一堆二进制属性,例如

attrs = set(['likes_coffee','has_curly_hair','has_dark_hair','drives_car','man_u_fan'])

数据集由一个制表符分隔的数据文件表示,该文件将一些属性分配给每个人,例如

john    likes_coffee
john    drives_car
john    has_curly_hair
jane    has_curly_hair
jane    man_u_fan
...

attrs有大约30,000元素,people可以和6,000,000一样大,但是数据稀疏,即每个人最多有30-40个属性

我正在寻找允许我使用的 python 数据结构/类:

  • 从对应的数据文件中快速创建代表数据集的matrix对象
  • 能够快速提取矩阵的各个元素以及行和列的块。例如,我想回答以下问题
    • “给我一份所有{'has_curly_hair','likes_coffee','man_u_fan'}的人的名单”
    • “给我一个{'mike','joe'}属性的联合”

我当前的实现为这两个集合使用一对数组和一个scipy 稀疏矩阵。所以如果

people = ['john','jane','mike','joe']
attrs = ['likes_coffee','has_curly_hair','has_dark_hair','drives_car','man_u_fan']

然后我将创建一个大小为4 X 5 的稀疏矩阵data,上面显示的示例数据将对应于元素

data[0,0]
data[0,3]
data[0,1]
data[1,1]
data[1,4]
...

我还维护了两个反向索引,这样我就不必过于频繁地调用 people.index('mike')attrs.index('has_curly_hair')

这工作正常,但我必须明确维护索引。这很麻烦,例如,当我有两个具有不同人员和/或属性集的数据集并且我需要匹配对应于两个稀疏矩阵中相同人员/属性的行/列时。

那么有没有一种替代方法可以让我避免使用整数索引,而是使用两组的实际元素来提取行/列,即类似

data['john',:]  # give me all attributes of 'john'
data[:,['has_curly_hair','drives_car']] # give me all people who 'has_curly_hair' or 'drives_car'

?

【问题讨论】:

  • 你考虑过使用pandas吗?
  • 看起来像一个简单的字典就可以完成的工作,除了矩阵创建可能需要一些逻辑来从字典中提取。即便如此,我还是第一次尝试 dict。

标签: python indexing scipy sparse-matrix


【解决方案1】:

假设没有库完全符合您的要求,您可以创建自己的类SparseMatrix 并重载运算符[]。这是一种方法(构造函数可能与您想要的不同):

class SparseMatrix():
    def __init__(self, x_label, y_label):
        self.data = {}
        for x,y in zip(x_label,y_label):
            print x,y
            self.data[x] = {}
            for attr in y:
                self.data[x][attr] = 1
        return

    def __getitem__(self, index):
        x,y = index
        if type(x) is str:
            if type(y) is str:
                return 1 if y in self.data[x] else 0
            if type(y) is slice:
                return self.data[x].keys()
        if type(x) is slice:
            if type(y) is str:
                res = []
                for key in self.data.keys():
                    if y in self.data[key]:
                        res.append(key)
                return res
            if type(y) is list:
                res = []
                for attr in y:
                    res += self.__getitem__((x,attr))
                return res

在 REPL 中,我得到:

> data = SparseMatrix(['john','jane','mike','joe'],[['likes_coffee','has_curly_hair'],['has_dark_hair'],['drives_car'],['man_u_fan']])

> data['john',:]
['has_curly_hair', 'likes_coffee']

> data[:,['has_curly_hair','drives_car']]
['john', 'mike']

【讨论】:

  • 谢谢。 def __getitem__(self, index,index_list=None): 中的 index_list=None 是什么?
  • @IZ 我实际上并不需要它,编辑我的答案以将其删除。
【解决方案2】:

sparse 格式之一实际上是字典。 dok_matrix 是字典子类,其中键的形式为 (1,100),(30,334)。那是 i,j 索引的元组。

但我在其他 SO 问题中发现,访问这种格式的元素实际上比常规字典访问要慢。即d[1,100] 比等效的dd[(1,100)] 慢。我发现构建一个常规字典最快,并使用update 将值添加到稀疏dok

但是,如果您想将矩阵转换为一种计算友好的格式,例如csrdok 会很有用。当然,您可以使用d[100,:] 访问稀疏矩阵,这是常规字典无法实现的。

对于某些用途,默认字典可以快速而有用。换句话说,一个字典,其中键是“人”,值是列表或其他具有“属性”键的字典。

无论如何,稀疏矩阵没有提供词索引。请记住,它的根源在于线性代数,计算矩阵乘积和大型稀疏数字矩阵的逆。它用于文本数据库是相对较新的。

【讨论】:

    猜你喜欢
    • 2018-06-18
    • 2019-03-12
    • 2019-08-01
    • 2012-01-15
    • 2014-05-12
    • 2018-05-06
    • 1970-01-01
    • 1970-01-01
    • 2013-04-12
    相关资源
    最近更新 更多