Lire un fichier CSV et le stocker dans une matrice

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour,
j'ai réalisé un script Matlab que j'ai traduit en Python grâce au script libermate. Et j'aimerais voir si la traduction fonction. Le problème c'est que dans mon script Matlab, je lit un fichier CSV et je le stocke dans une matrice, cependant, cette étape n'a pas été traduite.

J'ai donc essayé de corriger la chose et j'ai trouvé ceci dans la doc de Python :

1
2
with open('/.../eye-11h08.csv', 'rb') as f:
    data = csv.reader(f, delimiter=';', quoting=csv.QUOTE_NONE)

le seul problème, c'est que je ne connaît pas Python, j'arrive juste à le comprendre comme un français arrive à déchiffrer de l'espagnole, par comparaison avec le C++. Et je ne sais pas comment stocker les données de la fonction csv.reader pour qu'elle soient exploitable par le reste de l'algorithme.

Voici le début de mon code Matlab d'origine :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
data = csvRead(fullfile('/.../eye-11h08.csv'), ';');
X=data(:,2:15);
X = [X(:,1:3) X(:,12:14)]';
temps = data(:,1)';

X = X(:,1:9);
temps = temps(:,1:9);

clear data;

nbrSample = max(size(X));
nbrMeasure = min(size(X));

% Averaging
Xm = X - mean(X, 2)*ones(1,nbrSample);

% Whitening
[E,D]=eig(cov(Xm'));
Xw = E*D^(-0.5)*E'*Xm;
clear Xm;

%...

et voici le code Python traduit (j'ai remplacé le morceau non traduit de la lecture du CSV, mais l'utilisation de data ne marche pas) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import numpy as np
import scipy
import matcompat
import csv

# if available import pylab (from matlibplot)
try:
    import matplotlib.pylab as plt
except ImportError:
    pass

with open('/.../eye-11h08.csv', 'rb') as f:
    data = csv.reader(f, delimiter=';', quoting=csv.QUOTE_NONE)

    X = data[:,1:15.]
    X = np.array(np.hstack((X[:,0:3.], X[:,11:14.]))).conj().T
    temps = data[:,0].conj().T
    X = X[:,0:9.]
    temps = temps[:,0:9.]
    clear(data)
    nbrSample = matcompat.max(matcompat.size(X))
    nbrMeasure = matcompat.max(matcompat.size(X))
    #% Averaging
    Xm = X-np.dot(np.mean(X, 2.), np.ones(1., nbrSample))
    #% Whitening
    [E, D] = linalg.eig(np.cov(Xm.conj().T))
    Xw = np.dot(np.dot(np.dot(E, matixpower(D, -0.5)), E.conj().T), Xm)
    clear(Xm)
    #...

J'espère que vous pourrez m'aider :-)
Merci d'avance.

PS : pour ceux qui se demanderaient pourquoi j’utilise Python, c'est pcq c'est un des langage de script d'un logiciel.

Édité par Dark Patate

La curiosité est le plus beau des défauts

+0 -0
Staff

J'ai rien pour vérifier la (je suis dans le metro) mais un truc comme ça devrait fonctionner :

1
2
with open('/.../eye-11h08.csv', 'rb') as f:
    data = np.array([[float(e) for e in row] for row in csv.reader(f, delimiter=';', quoting=csv.QUOTE_NONE)])

J'ai supposé que ton csv ne contenait que des float.

Tu peux virer l'indentation après ça. Une fois les données lues, tu peux sortir du with qui fermera le fichier. J'ai pas le temps là de regarder si la conversion à été correct mais à première vue je dirais que tu va avoir un problème avec clear, il ne semble pas avoir été converti.

+0 -0
Auteur du sujet

Merci pour ton aide, j'ai supprimé les clear pour être sûr. En revanche, j'ai un petit problème de lecture, je reçois ce message :

1
2
3
4
Traceback (most recent call last):
  File "algoICA-final2.py", line 14, in <module>
    data = np.array([[float(e) for e in row] for row in csv.reader(f, delimiter=';', quoting=csv.QUOTE_NONE)])
ValueError: could not convert string to float: 

Voici le début de mon fichier CSV (c'est peut-être pcq les nombres sont sous format scientifique qu'il le considère comme une string ?)

1
2
3
4
0.0000000000e+00;-3.6645928958e-08;-3.7489257920e-08;-3.8226517063e-08;-3.7996983338e-08;-3.4155732465e-08;-3.8469352148e-08;-3.4522145143e-08;-3.8513462641e-08;-3.5356720218e-08;-3.5012249100e-08;-3.7211179915e-08;-3.6522351365e-08;-3.5608309190e-08;-3.7785071072e-08;-1.3499857232e-08;-1.5049579360e-08;
7.8125000000e-03;3.0628651447e+00;3.5132587361e+00;2.9727178093e+00;2.7925946820e+00;2.2520966383e+00;2.7025331188e+00;1.8016601613e+00;4.0537138913e+00;2.7025331165e+00;2.8826562434e+00;3.1529267087e+00;2.6123857808e+00;4.2339227893e+00;1.5314754729e+00;9.8082182376e-09;-1.7566292451e-01;
1.5625000000e-02;1.0569686807e+01;1.3326838209e+01;9.7657807595e+00;7.7982235679e+00;1.0993581234e+01;1.1498761329e+01;6.7048719853e+00;1.4275173552e+01;1.1048367726e+01;1.2655592888e+01;1.1733588532e+01;8.8932809043e+00;1.6963645372e+01;6.2758604025e+00;3.5132592268e-01;-5.1319858961e-01;
//...

La curiosité est le plus beau des défauts

+0 -0
Staff

Attend, déjà tu utilise python 2 ou python 3 ?

edit: bon manifestement tu utilise python2.

Le lecteur de csv de python est générique, il est pas fait que pour lire lire les matrices (puisqu'un fichier csv peut contenir n'importe quoi). Il n'y a que matlab qui fait cette supposition. Donc python renvois des strings à chaque fois. dans le code que je t'ai donné je demande explicitement de les convertir en float mais ça marche pas parce que dans ton csv il y a un ; final. Donc selon le format, à chaque ligne il y a une colonne vide final. Or Python ne peut donc pas convertir une chaine vide en float. La solution du coup :

1
data = np.array([[float(e) for e in row if e] for row in csv.reader(f, delimiter=';', quoting=csv.QUOTE_NONE)])

Édité par Kje

+0 -0
Staff

j'ai fais un edit avec l'explication du problème et une solution. Chez moi ça fonctionne.

Au passage ligne 26 de ton script tu risque d'avoir de soucis car linalg n'est pas importé spécifiquement. Rajoute from numpy import linalg au début du script.

Les clear(maVariable) ne peuvent être remplacé strictement car il est impossible de supprimer manuellement une variable. Le plus proche serait de le remplacer par del maVariable qui la majorité du temps fera la même chose.

+0 -0
Auteur du sujet

Pour les clear, je les avais mis pour éviter que Matlab remplisse toute la ram du PC ^^.

Par contre j'ai une autre erreur :

1
2
3
4
Traceback (most recent call last):
  File "algoICA-final2.py", line 23, in <module>
    nbrSample = matcompat.max(matcompat.size(X))
AttributeError: 'module' object has no attribute 'max'

C'est peut-être à cause de la version de Python entre la tienne et la mienne ? (je sais pas quelles sont les différences).

PS : j'ai aussi supprimé les lignes 18 et 19 qui étaient là uniquement pour prendre moins de données. Car python m'a sortit une erreur pour ces lignes : IndexError: too many indices

La curiosité est le plus beau des défauts

+0 -0
Staff

Je pense que matcompat est un module lié à ton script de conversion et est tout sauf standard. En l'occurrence vu ton code MATLAB je pense que tu devrais plutôt faire :

1
nbrSample = np.max(X.shape)

Et idem à la ligne en dessous avec le min.

Par contre c'est moche et dangereux comme ligne. Si tu sais que ton nombre d'exemple est le nombre de ligne, ça serait plus clean :

1
nbrSample = X.shape[0]

(Ou remplace le 0 par 1 si c'est le nombre de colonne que tu veux).

J'ai l'impression que ton script de conversion est fait par quelqu'un qui connait assez peu numpy au final.

Il va vraiment que je prenne le temps de rédiger une intro à numpy sur ce site.

+0 -0
Auteur du sujet

Je suis d'accord que la façon de faire n'est pas très propre :p c'est juste que dans mon Matlab, au début j'avais les données dans un sens, puis dans l'autre. Alors pour m'affranchir des transposées, j'ai utilisé cette technique en attendant la version définitive.

C'est le deuxième script que j'ai trouvé en faisant des recherches sur Google, le premier, je n'ai pas réussi à le faire fonctionner.

Moi, faudrait que je reprenne mon apprentissage du python, pcq jouer à l'apprenti sorcier, ça marche pas des masses ! ^^ Mais un cours pour faire des maths avec Python ça m’intéresserait ! Pcq, en essayant de faire ma première traduction en C++, je me suis rendu compte que le C++ est pas vraiment fait pour ça…

J'ai une autre erreur (j'ai dû corriger les indices avant, ils étaient en float au lieu d'être en int) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Traceback (most recent call last):
  File "algoICA-final2.py", line 27, in <module>
    Xm = X-np.dot(np.mean(X, 2), np.ones(1, nbrSample))
  File "/usr/lib/python2.7/dist-packages/numpy/core/fromnumeric.py", line 2716, in mean
    out=out, keepdims=keepdims)
  File "/usr/lib/python2.7/dist-packages/numpy/core/_methods.py", line 52, in _mean
    rcount = _count_reduce_items(arr, axis)
  File "/usr/lib/python2.7/dist-packages/numpy/core/_methods.py", line 46, in _count_reduce_items
    items *= arr.shape[ax]
IndexError: tuple index out of range

Si je comprends bien et que je me souviens de ce que j'ai un peu appris en Python, l'indice pour le tuple (un genre de tableau, non ?) est en-dehors des clous. Mais je vois pas où est ce tuple…

Édité par Dark Patate

La curiosité est le plus beau des défauts

+0 -0
Staff

C'est bien ça l'erreur mais si il parle de tuple, c'est à l'intérieur de la fonction que tu utilise.

Ça vient de cette ligne :

1
Xm = X-np.dot(np.mean(X, 2), np.ones(1, nbrSample))

Le deuxième argument de mean est l'axe sur lequel faire la moyenne. Si ton tableau X n'a que deux dimensions cette valeur ne peut être que 0 ou 1. Remplace le 2 par 1.

+0 -0
Auteur du sujet

Ok, je vois que la traduction n'est pas super efficace :/
J'obtiens une autre erreur : ValueError: matrices are not aligned, j'ai fait qq recherches et j'ai vu que c'est un problème de dimension de matrices. J'ai donc fait fait ça :

1
print np.mean(X, 1).shape

Et je vois qu'il y a effectivement un problème : (6,), visiblement il manque une dimension…

Si ça continu comme ça, je vais abandonner, sinon je vais passer ma journée à t'embêter dès que le compilateur me sortira une erreur…

Édité par Dark Patate

La curiosité est le plus beau des défauts

+0 -0
Staff

Bon c'est pas un compilateur mais un interpréteur. np.mean(X, 1) fait la moyenne des données selon un des axes donc ça renvois un vecteur à une seule dimension. Tu voudrais avoir quoi ?

Il serait peut être plus simple que tu m'explique ce que tu veux faire avec tes données, et je pourrais t'expliquer comment faire.

+0 -0
Auteur du sujet

Oui, c'est pour ça que j'ai mis compilateur en italique (le mot interpréteur m'était sortit de la tête).
Je veux bien un vecteur colonne, mais visiblement, ça ne marche pas.

Si tu veux, je peux te donner tout le code Matlab, mais pour résumer, je veux utiliser l'algorithme ICA pour créer trois classes à mes données. Celles ci étant enregistrées par six capteurs. Les étapes dans l'ordre :

  1. Extraire les données du fichier et les mettre sous la forme d'une matrice (nbrMesure*nbrEchantillon) ($X$).
  2. Faire un moyennage des mesures. Pour cela, je soustrait le vecteur colonne des moyennes. Résultat ($X_m$).
  3. Ensuite je réalise un blanchiment pour décorreller les données en suivant la formule suivant :
    $$X_w = E\cdot D^{-1/2}\cdot E^T\cdot X_m$$
    avec E la matrice des vecteurs propres et D la matrice diagonale des valeurs propres.
  4. Ensuite j'applique l'algorithme ICA en suivant cette méthode : fastICA (en fait, toute la méthode y est décrite)
  5. Pour finir, je fait une corrélation entre les trois vecteurs trouvés par l'ICA et le premier et le dernier de la matrice X pour pouvoir identifier lequel est lequel.

Les mesures sont des données récupérées d'un EEG et mon but c'est de récupérer uniquement les signaux des yeux, et de les classer (droit et gauche).

Édité par Dark Patate

La curiosité est le plus beau des défauts

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte