例如我有一个coo_matrix A:
import pandas as pd
from patsy import dmatrices
import statsmodels.api as sm
y, X = dmatrices( 'label ~ age + gender', data=df, return_type='dataframe')
mod = sm.Logit(y, X)
res = mod.fit()
print res.summary()
如何获得结果[0,0,0,1],表示前3列包含非零值,只有第4列全部为零。
PS:无法将A转换为其他类型
PS2:我尝试使用import scipy.sparse as sp
A = sp.coo_matrix([3,0,3,0],
[0,0,2,0],
[2,5,1,0],
[0,0,0,0])
,但似乎我的实现不是很优雅。
答案 0 :(得分:1)
方法#1 我们可以做这样的事情 -
# Get the columns indices of the input sparse matrix
C = sp.find(A)[1]
# Use np.in1d to create a mask of non-zero columns.
# So, we invert it and convert to int dtype for desired output.
out = (~np.in1d(np.arange(A.shape[1]),C)).astype(int)
或者,为了缩短代码,我们可以使用减法 -
out = 1-np.in1d(np.arange(A.shape[1]),C)
分步运行 -
1)从中输入数组和稀疏矩阵:
In [137]: arr # Regular dense array
Out[137]:
array([[3, 0, 3, 0],
[0, 0, 2, 0],
[2, 5, 1, 0],
[0, 0, 0, 0]])
In [138]: A = sp.coo_matrix(arr) # Convert to sparse matrix as input here on
2)获取非零列索引:
In [139]: C = sp.find(A)[1]
In [140]: C
Out[140]: array([0, 2, 2, 0, 1, 2], dtype=int32)
3)使用np.in1d
获取非零列的掩码:
In [141]: np.in1d(np.arange(A.shape[1]),C)
Out[141]: array([ True, True, True, False], dtype=bool)
4)反转它:
In [142]: ~np.in1d(np.arange(A.shape[1]),C)
Out[142]: array([False, False, False, True], dtype=bool)
5)最后转换为int dtype:
In [143]: (~np.in1d(np.arange(A.shape[1]),C)).astype(int)
Out[143]: array([0, 0, 0, 1])
替代减法方法:
In [145]: 1-np.in1d(np.arange(A.shape[1]),C)
Out[145]: array([0, 0, 0, 1])
方法#2 这是另一种方式,可能是使用matrix-multiplication
更快的方法 -
out = 1-np.ones(A.shape[0],dtype=bool)*A.astype(bool)
运行时测试
让我们在一个庞大且非常稀疏的矩阵上测试所有发布的方法 -
In [29]: A = sp.coo_matrix((np.random.rand(4000,4000)>0.998).astype(int))
In [30]: %timeit 1-np.in1d(np.arange(A.shape[1]),sp.find(A)[1])
100 loops, best of 3: 4.12 ms per loop # Approach1
In [31]: %timeit 1-np.ones(A.shape[0],dtype=bool)*A.astype(bool)
1000 loops, best of 3: 771 µs per loop # Approach2
In [32]: %timeit 1 - (A.col==np.arange(A.shape[1])[:,None]).any(axis=1)
1 loops, best of 3: 236 ms per loop # @hpaulj's soln
In [33]: %timeit (A!=0).sum(axis=0)==0
1000 loops, best of 3: 1.03 ms per loop # @jez's soln
In [34]: %timeit (np.sum(np.absolute(A.toarray()), 0) == 0) * 1
10 loops, best of 3: 86.4 ms per loop # @wwii's soln
答案 1 :(得分:1)
实际的逻辑操作可以这样执行:
b = (A!=0).sum(axis=0)==0
# matrix([[False, False, False, True]], dtype=bool)
现在,为了确保我完全回答你的问题,我最好告诉你如何从布尔转换为整数(尽管如此,对于我能想到的大多数应用程序,你如果你坚持使用numpy
s数组,可以在bool
和朋友中做更多事情:
b = b.astype(int)
#matrix([[0, 0, 0, 1]])
无论哪种方式,然后从matrix
转换为list
,您都可以这样做:
c = list(b.flat)
# [0, 0, 0, 1]
......尽管如此,我不确定这是最好的事情:对于我能想象的大多数应用程序,我可能只会转换为一维numpy.array
c = b.A.flatten()
代替。
答案 2 :(得分:1)
最近
scipy.sparse.coo_matrix how to fast find all zeros column, fill with 1 and normalize
类似,除了它想用1填充这些列并将它们标准化。
我立即建议了转置的lil
格式。全0列将是此格式的空列表。但坚持我建议的coo
格式
np.nonzero(~(Mo.col==np.arange(Mo.shape[1])[:,None]).any(axis=1))[0]
或此1/0格式
1 - (Mo.col==np.arange(Mo.shape[1])[:,None]).any(axis=1)
在功能上与:
相同1 - np.in1d(np.arange(Mo.shape[1]),Mo.col)
sparse.find
将矩阵转换为csr
以对重复项进行求和并消除重复项,然后返回coo
以获取data
,row
和{ {1}}属性(它返回)。
col
和Mo.nonzero
属性之前, A.data != 0
使用col
消除0。
row
解决方案需要将np.ones(A.shape[0],dtype=bool)*A.astype(bool)
格式转换为A
格式才能进行乘法。
csr
也转换为(A!=0).sum(axis=0)
,因为列(或行)总和是通过矩阵乘法完成的。
因此,无转换要求是不现实的,至少在稀疏格式的范围内。
===============
对于Divakar的测试用例,我的csr
版本非常慢;小的可以,但是用1000列创建了太大的测试数组。
在足够稀疏且具有多个0列的矩阵上进行测试:
==
答案 3 :(得分:0)
转换为数组或密集矩阵,沿第一轴求和绝对值,测试结果为零,转换为int
>>> import numpy as np
>>> (np.sum(np.absolute(a.toarray()), 0) == 0) * 1
array([0, 0, 0, 1])
>>> (np.sum(np.absolute(a.todense()), 0) == 0) * 1
matrix([[0, 0, 0, 1]])
>>>
>>> np.asarray((np.sum(np.absolute(a.todense()), 0) == 0), dtype = np.int32)
array([[0, 0, 0, 1]])
>>>
第一个是最快的 - 在我的机器上你的例子是24美元。
对于使用np.random.randint(0,3,(1000,1000))
制作的矩阵,我的机器上的所有矩阵都是25 mS。