python:我可以在没有(显式)使用整数索引的情况下使用稀疏矩阵表示吗?

时间:2015-11-09 20:08:36

标签: python indexing scipy sparse-matrix

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

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']

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

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'

2 个答案:

答案 0 :(得分:1)

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

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']

答案 1 :(得分:0)

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

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

但如果您想将矩阵转换为dok等计算友好格式之一,csr非常有用。当然,您可以使用d[100,:]访问稀疏矩阵,这对于常规字典来说是不可能的。

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

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