2015-08-11 4 views
7

Ich habe eine numpy Array:Welche Art von Python-Array wäre das? Gibt es das schon in Python?

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

Die 4 Spalten m sind beschriftet:

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

Ich möchte o um ein Objekt schneiden können, so dass:

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

Gibt es ein vorhandenes Python-Objekt, mit dem ich das machen könnte?

Ich habe mir Scipy Sparse Matrices angesehen, aber es ist nicht ganz das, was ich suche.

ein Update am 17. August 2015: ich mit ein paar Ideen ein Spiel gehabt haben, um und kam mit dieser, die als fast das gleiche ist, was ich letzte Woche beschrieben:

Antwort

3

können Sie ganz nah an, was Sie wollen, indem Sie eine cl definieren ass m und c enthalten:

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)) 

Returns:

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] 

(. Es könnte einfacher sein, die Indizierung zu verwenden, m[i][m[i]!=0 und c[m[i]!=0] direkt, obwohl)

2

Sie könnten pandas verwenden (http://pandas.pydata.org/). (Da Sie scipy/numpy ausprobiert haben, die keine Standardbibliothek Python-Pakete sind, nehme ich an, dass es in Ordnung ist, ein anderes Paket vorzuschlagen).

Ein DataFrame ist ein Objekt, mit dem Sie alle Ihre Operationen ausführen können, und vieles mehr.

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.]) 

# ... 

Sie könnten auch Spaltenbeschriftung und Wert kombinieren, da die normale Rückkehr aus dem dropna ein Datenrahmen ist.

Am besten versuchen Sie einfach Pandas und sehen Sie, ob es Ihren Bedürfnissen entspricht. Und werfen Sie auch einen Blick auf das große Intro (http://pandas.pydata.org/pandas-docs/stable/10min.html).

2

Sie können zu nahe kommen, was man mit einem CSR-Sparse Matrix wollen:

import scipy.sparse as sps 

m_csr = sps.csr_matrix(m) 

Sie können nun Funktionen implementieren ähnlich dem, was Sie nach wie diese sind:

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

diese Funktionen verwenden wir erhalten:

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

Dies wird sehr effizient auf große Matrizen, obwohl die synta x ist nicht ganz das, was du wolltest.

1

Sie können eine verschachtelte Klasse verwenden und überlasten die __getitem__ Attribut Ihrer Objekte:

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

Demo:

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]