这是一个什么样的Python数组?它是否已经存在于Python中



我有一个numpy数组:

m = array([[4, 0, 9, 0],
          [0, 7, 0, 0],
          [0, 0, 0, 0],
          [0, 0, 0, 5]])

m的4列标为:

c = array([ 10, 20, 30, 40])

我希望能够切片一个对象o,这样:

o.vals[0,:] = array([4, 9])
o.vals[1,:] = array([7,])
o.vals[2,:] = array([])
o.vals[3,:] = array([5])
o.cols[0,:] = array([10, 30] )# the non-zero column labels from row 0
o.cols[1,:] = array([20,])
o.cols[2,:] = array([])
o.cols[3,:] = array([40])

是否有一个现有的Python对象可以让我这样做?

我已经看过Scipy稀疏矩阵,但它不是我所寻找的。

2015年8月17日的更新:我已经玩了一些想法,并提出了这个,这几乎与我上周描述的相同:

    https://github.com/jsphon/NumericalFunctions/blob/master/jagged_array/JaggedKeyValueArray.rst
  • https://github.com/jsphon/NumericalFunctions/blob/master/jagged_array/jagged_key_value_array.py

你可以通过定义一个包含mc的类来接近你想要的:

import numpy as np
class O(object):
    def __init__(self, m, c):
        self.m, self.c = m, c
    def vals(self, i):
        return self.m[i][self.m[i]!=0]
    def cols(self, i):
        return self.c[self.m[i]!=0]

m = np.array([[4, 0, 9, 0],
          [0, 7, 0, 0],
          [0, 0, 0, 0],
          [0, 0, 0, 5]])
c = np.array([ 10, 20, 30, 40])
o = O(m, c)
for i in range(4):
    print 'o.vals({0:d}) = {1}'.format(i, o.vals(i))
for i in range(4):
    print 'o.cols({0:d}) = {1}'.format(i, o.cols(i))

的回报:

o.vals(0) = [4 9]
o.vals(1) = [7]
o.vals(2) = []
o.vals(3) = [5]
o.cols(0) = [10 30]
o.cols(1) = [20]
o.cols(2) = []
o.cols(3) = [40]

(直接使用索引m[i][m[i]!=0c[m[i]!=0]可能更容易)

您可以使用pandas (http://pandas.pydata.org/)。(因为你尝试了scipy/numpy,这不是标准库Python包,我认为建议另一个包是可以的)。

DataFrame是一个对象,它可以让你完成所有的操作,甚至更多。

import numpy as np                                                                
import pandas as pd                                                               
m = array([[4, 0, 9, 0], [0, 7, 0, 0], [0, 0, 0, 0], [0, 0, 0, 5]])               
# create a dataframe                                                                                  
df = pd.DataFrame(m, columns=[10,20,30,40])   
# replace 0 with NaN (to make use of pandas `dropna`)                                    
df.replace(0, np.NaN, inplace=True)
# values per row                                                                  
df.irow(0).dropna().as_matrix()                                                   
array([ 4.,  9.])                                                                 
df.irow(1).dropna().as_matrix()                                                   
array([ 7.])                                                                      
df2.irow(2).dropna().as_matrix()                                                  
array([], dtype=float64)
# column labels (as list)                                                         
df.irow(1).dropna().index.tolist()
[10, 30]
# or non-zero values per column?
df.icol(0).dropna().as_matrix()
array([ 4.])
# ...

您也可以组合列标签和值,因为dropna的正常返回是一个DataFrame。

non_zero_1 = df.irow(0).dropna()
labels_1 = non_zero_1.index
Int64Index([10, 30], dtype='int64')

最好试试Pandas,看看它是否符合你的需求。也可以看一下精彩的介绍(http://pandas.pydata.org/pandas-docs/stable/10min.html)

你可以用CSR稀疏矩阵来接近你想要的:

import scipy.sparse as sps
m_csr = sps.csr_matrix(m)

你现在可以实现类似于你所追求的函数,像这样:

def vals(sps_mat, row):
    row_slice = slice(sps_mat.indptr[row], sps_mat.indptr[row+1])
    return sps_mat.data[row_slice]
def cols(sps_mat, col_labels, row):
    col_labels = np.asarray(col_labels)
    row_slice = slice(sps_mat.indptr[row], sps_mat.indptr[row+1])
    return col_labels[sps_mat.indices[row_slice]]
使用这个函数,我们得到:
>>> for row in range(m_csr.shape[0]):
...     print vals(m_csr, row)
...
[4 9]
[7]
[]
[5]
>>> for row in range(m_csr.shape[0]):
...     print cols(m_csr, [10, 20, 30, 40], row)
...
[10 30]
[20]
[]
[40]

这对于大的矩阵是非常有效的,尽管语法不是你想要的。

您可以使用嵌套类并重载对象的__getitem__属性:

import numpy as np
class indexer:
   def __init__(self,arr):
      self.arr=arr
      self.d=self.caldict(self.arr)
      self.vals=self.values(self.arr,self.d)
      self.cols=self.columns(self.d)
   def caldict(self,arr,dd={}):
      inds=np.array(np.nonzero(arr)).T
      for i,j in inds:
          dd.setdefault(i,[]).append(j)
      return dd
   class values:
        def __init__(self,arr,d):
           self.arr=arr
           self.d=d
        def __getitem__(self,index):
          try:
            return self.arr.take(index,axis=0)[self.d[index]]
          except KeyError:
            return []
   class columns:
        def __init__(self,d):
           self.d=d
           self.c=np.array([ 10, 20, 30, 40])
        def __getitem__(self,index):
          try:
             return self.c.take(self.d[index])
          except KeyError:
             return []
演示:

m=np.array([[4, 0, 9, 0],
       [0, 7, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 5]])
o=indexer(m)
print o.vals[0],'n',o.vals[1],'n',o.vals[2],'n',o.vals[3]
print '------------------'
print o.cols[0],'n',o.cols[1],'n',o.cols[2],'n',o.cols[3]
[4 9] 
[7] 
[] 
[5]
------------------
[10 30] 
[20] 
[] 
[40]

最新更新