python:我可以在不(明确地)使用整数索引的情况下使用稀疏矩阵表示吗?
python: can I have a sparse matrix representation without (explicitly) using integer indices?
我有一个数据集,它本质上是一个表示两组元素之间关系的稀疏二进制矩阵。例如,让第一组是人(用他们的名字表示),例如像这样:
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 中寻找数据 structure/class,它可以让我:
- 从相应的数据文件
中快速创建表示数据集的 matrix
对象
- 能够快速提取矩阵的各个元素及其行和列的块。例如,我想回答这样的问题
- "Give me a list of all people with
{'has_curly_hair','likes_coffee','man_u_fan'}
"
- "Give me a union of attributes of
{'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')
这工作正常,但我必须明确维护索引。这很麻烦,例如,当我有两个具有不同人 and/or 属性集的数据集并且我需要匹配来自两个稀疏矩阵的相同 person/attribute 对应的 rows/columns 时。
那么有没有一种替代方法可以让我避免使用整数索引,而是使用两个集合的实际元素来提取 rows/columns,即类似
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'
?
其中一种 sparse
格式实际上是字典。 dok_matrix
是一个字典子类,其中键的形式为 (1,100)
、(30,334)
。这是 i,j 索引的元组。
但我在其他 SO 问题中发现,访问这种格式的元素实际上比常规字典访问要慢。也就是说 d[1,100]
比等效的 dd[(1,100)]
慢。我发现建立一个正则字典是最快的,然后使用 update
将值添加到稀疏 dok
.
但是如果您想将矩阵转换为计算友好的格式之一,例如 csr
,dok
会很有用。当然,您可以使用 d[100,:]
访问稀疏矩阵,这对于常规字典来说是不可能的。
对于某些用途,默认词典可能既快捷又有用。换句话说,一个字典,其中键是 'people',值是列表或其他具有 'attribute' 键的字典。
不管怎么说,稀疏矩阵没有提供词索引。请记住,它的根源在于线性代数,计算矩阵乘积和大型稀疏数字矩阵的逆。它用于文本数据库的时间相对较新。
假设没有库完全符合您的要求,您可以创建自己的 class 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']
我有一个数据集,它本质上是一个表示两组元素之间关系的稀疏二进制矩阵。例如,让第一组是人(用他们的名字表示),例如像这样:
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 中寻找数据 structure/class,它可以让我:
- 从相应的数据文件 中快速创建表示数据集的
- 能够快速提取矩阵的各个元素及其行和列的块。例如,我想回答这样的问题
- "Give me a list of all people with
{'has_curly_hair','likes_coffee','man_u_fan'}
" - "Give me a union of attributes of
{'mike','joe'}
"
- "Give me a list of all people with
matrix
对象
我当前的实现对两个集合使用一对数组和一个 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')
这工作正常,但我必须明确维护索引。这很麻烦,例如,当我有两个具有不同人 and/or 属性集的数据集并且我需要匹配来自两个稀疏矩阵的相同 person/attribute 对应的 rows/columns 时。
那么有没有一种替代方法可以让我避免使用整数索引,而是使用两个集合的实际元素来提取 rows/columns,即类似
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'
?
其中一种 sparse
格式实际上是字典。 dok_matrix
是一个字典子类,其中键的形式为 (1,100)
、(30,334)
。这是 i,j 索引的元组。
但我在其他 SO 问题中发现,访问这种格式的元素实际上比常规字典访问要慢。也就是说 d[1,100]
比等效的 dd[(1,100)]
慢。我发现建立一个正则字典是最快的,然后使用 update
将值添加到稀疏 dok
.
但是如果您想将矩阵转换为计算友好的格式之一,例如 csr
,dok
会很有用。当然,您可以使用 d[100,:]
访问稀疏矩阵,这对于常规字典来说是不可能的。
对于某些用途,默认词典可能既快捷又有用。换句话说,一个字典,其中键是 'people',值是列表或其他具有 'attribute' 键的字典。
不管怎么说,稀疏矩阵没有提供词索引。请记住,它的根源在于线性代数,计算矩阵乘积和大型稀疏数字矩阵的逆。它用于文本数据库的时间相对较新。
假设没有库完全符合您的要求,您可以创建自己的 class 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']