2009-04-04 9 views
4

Hier, j'avais besoin d'un type de matrice en Python.Matrices en Python

Apparemment, une réponse triviale à ce besoin serait d'utiliser numpy.matrix(), mais le problème supplémentaire que j'ai est que je voudrais qu'une matrice stocke des valeurs arbitraires avec des types mixtes, de manière similaire à une liste. numpy.matrix ne l'effectue pas. Un exemple est

>>> numpy.matrix([[1,2,3],[4,"5",6]]) 
matrix([['1', '2', '3'], 
     ['4', '5', '6']], 
     dtype='|S4') 
>>> numpy.matrix([[1,2,3],[4,5,6]]) 
matrix([[1, 2, 3], 
     [4, 5, 6]]) 

Comme vous pouvez le voir, le numpy.matrix doit être homogène dans le contenu. Si une valeur de chaîne est présente dans mon initialisation, chaque valeur est implicitement stockée en tant que chaîne. Cela est également confirmé en accédant aux valeurs uniques

>>> numpy.matrix([[1,2,3],[4,"5",6]])[1,1] 
'5' 
>>> numpy.matrix([[1,2,3],[4,"5",6]])[1,2] 
'6' 

Maintenant, le type de liste Python peut à la place accepter des types mixtes. Vous pouvez avoir une liste contenant un entier et une chaîne, tous deux conservant leur type. Ce dont j'aurais besoin est quelque chose de similaire à une liste, mais opérant dans un comportement semblable à une matrice. Par conséquent, j'ai dû implémenter mon propre type. J'avais deux choix pour l'implémentation interne: liste contenant des listes et dictionnaires. Les deux solutions présentent des inconvénients:

  • La liste des listes nécessite une synchronisation minutieuse des tailles des différentes listes. Échanger deux lignes est facile. Échanger deux colonnes est moins facile. Supprimer une rangée est facile aussi.
  • Les dictionnaires (avec un tuple comme clé) sont légèrement meilleurs, mais vous devez définir les limites de votre clé (par exemple, vous ne pouvez pas insérer l'élément 5,5 si votre matrice est 3x3) et ils sont plus complexes permet d'insérer, de supprimer ou d'échanger des colonnes ou des lignes.

Édition: clarification. La raison concrète pour laquelle j'ai besoin de cette fonctionnalité est parce que je lis des fichiers CSV. Une fois que je rassemble les valeurs d'un fichier CSV (valeurs qui peuvent être une chaîne, des entiers, des flottants), je voudrais effectuer l'échange, la suppression, l'insertion et d'autres opérations semblables. Pour cette raison j'ai besoin d'une "liste matricielle".

Mes curiosités sont:

  • savez-vous si un type de données Python fournissant ce service existe déjà (peut-être dans une bibliothèque « non inclus batterie » là-bas)?
  • Pourquoi ce type de données n'est-il pas fourni dans la bibliothèque standard? Un intérêt trop restreint peut-être?
  • Comment auriez-vous résolu ce besoin? Dictionnaire, liste ou autre solution plus intelligente?

Répondre

10

Vous pouvez avoir des types inhomogène si votre dtype est object:

In [1]: m = numpy.matrix([[1, 2, 3], [4, '5', 6]], dtype=numpy.object) 
In [2]: m 
Out[2]: 
matrix([[1, 2, 3], 
     [4, 5, 6]], dtype=object) 
In [3]: m[1, 1] 
Out[3]: '5' 
In [4]: m[1, 2] 
Out[4]: 6 

Je ne sais pas à quoi cela vous fait autre que FancyIndexing, parce que, comme Don a fait remarquer, vous ne pouvez pas faire avec les mathématiques cette matrice.

5

Je suis curieux de savoir pourquoi vous voulez cette fonctionnalité; si je comprends bien, la raison d'avoir des matrices (en numpy), est principalement de faire des mathématiques linéaires (transformations matricielles et ainsi de suite).

Je ne suis pas sûr de ce que la définition mathématique serait pour le produit d'une décimale et une chaîne.

En interne, vous voudrez probablement examiner les implémentations matricielles fragmentaires (http://www.inf.ethz.ch/personal/arbenz/pycon03_contrib.pdf). Il y a beaucoup de façons de le faire (hash, liste, liste chaînée), et chacun a ses avantages et ses inconvénients. Si votre matrice ne va pas avoir beaucoup de zéros ou de zéros, vous pouvez abandonner les implémentations éparses.

+0

La raison en est que j'ai besoin de stocker des valeurs arbitraires lues à partir d'un fichier csv, et ces valeurs peuvent être des chaînes, ou des flottants, ou des entiers. Le module csv me permet de lire un fichier csv ligne par ligne, mais pour le stocker en tant que "matrice" c'est à moi de décider. –

+0

Vous ne décrivez aucun type de "matrice" du tout. Vous décrivez une liste de tuples. – kquinn

+0

Oui, c'est. Mais malheureusement, je veux être en mesure d'effectuer des opérations sur cette liste de tuples, similaire aux opérations que je ferais sur une matrice: échange de lignes, échange de colonnes, insertion/suppression de colonnes, etc ... –

3

Avez-vous regardé les capacités de numpy.recarray?

Par exemple ici: http://docs.scipy.org/doc/numpy/reference/generated/numpy.recarray.html

Il est conçu pour permettre des tableaux avec types de données hétérogènes.

Je ne sais pas si un tableau conviendra à vos besoins, ou si vous avez vraiment besoin d'une matrice - je n'ai pas travaillé avec les matrices numpy. Mais si un tableau est assez bon, recarray pourrait fonctionner.

+0

le seul problème que je vois avec l'utilisation de recarrays (peut-être que je me trompe, je n'ai aucune expérience réelle avec eux) est qu'il serait incapable d'échanger des colonnes facilement. – Autoplectic

+0

Je dirais que l'échange de lignes et de colonnes est nécessaire, un tableau est simple, pas la bonne structure de données. Vous avez besoin que chaque élément soit indépendant l'un de l'autre. –

0

Avez-vous considéré le module csv pour travailler avec des fichiers CSV?

Python docs for csv module

+0

csv fournit des données ligne par ligne et ne renvoie l'enregistrement qu'en tant que chaînes. J'utilise csv pour lire le fichier, mais j'ai besoin d'un type de données plus intelligent pour effectuer les transformations dont j'ai besoin. –

1

Check out sympy - il fait tout à fait un bon travail au polymorphisme dans ses matrices et vous vous avez des opérations sur sympy.matrices.Matrix objets comme col_swap, col_insert, col_del, etc ...

 
In [2]: import sympy as s 
In [6]: import numpy as np 

In [11]: npM = np.array([[1,2,3.0], [4,4,"abc"]], dtype=object) 
In [12]: npM 
Out[12]: 
[[1 2 3.0] 
[4 4 abc]] 

In [14]: type(npM[0][0]) 
Out[14]: 
In [15]: type(npM[0][2]) 
Out[15]: 
In [16]: type(npM[1][2]) 
Out[16]: 


In [17]: M = s.matrices.Matrix(npM) 
In [18]: M 
Out[18]: 
⎡1 2 3.0⎤ 
⎢   ⎥ 
⎣4 4 abc⎦ 


In [27]: type(M[0,2]) 
Out[27]: 
In [28]: type(M[1,2]) 
Out[28]: 

In [29]: sym= M[1,2] 
In [32]: print sym.name 
abc 

In [34]: sym.n 
Out[34]: 
In [40]: sym.n(subs={'abc':45}) 
Out[40]: 45.0000000000000 

1

Peut-être est une réponse tardive, mais , pourquoi ne pas utiliser pandas?