J'utilise le code suivant pour créer un numpy-ndarray. Le fichier comporte 9 colonnes. Je tape explicitement chaque colonne:
dataset = np.genfromtxt("data.csv", delimiter=",",dtype=('|S1', float, float,float,float,float,float,float,int))
Maintenant, je voudrais obtenir des statistiques descriptives pour chaque colonne (min, max, stdev, moyenne, médiane, etc.). Ne devrait-il pas y avoir un moyen facile de le faire?
J'ai essayé ceci:
from scipy import stats
stats.describe(dataset)
mais cela renvoie une erreur: TypeError: cannot perform reduce with flexible type
Ma question est: Comment puis-je obtenir des statistiques descriptives du numpy-ndarray créé.
Ce n'est pas une jolie solution, mais cela fait le travail. Le problème est qu'en spécifiant plusieurs dtypes, vous créez essentiellement un tableau 1D de tuples (en fait np.void
), Qui ne peut pas être décrit par les statistiques car il comprend plusieurs types différents, y compris. cordes.
Cela pourrait être résolu soit en le lisant en deux tours, soit en utilisant pandas avec read_csv
.
Si vous décidez de vous en tenir à numpy
:
import numpy as np
a = np.genfromtxt('sample.txt', delimiter=",",unpack=True,usecols=range(1,9))
s = np.genfromtxt('sample.txt', delimiter=",",unpack=True,usecols=0,dtype='|S1')
from scipy import stats
for arr in a: #do not need the loop at this point, but looks prettier
print(stats.describe(arr))
#Output per print:
DescribeResult(nobs=6, minmax=(0.34999999999999998, 0.70999999999999996), mean=0.54500000000000004, variance=0.016599999999999997, skewness=-0.3049304880932534, kurtosis=-0.9943046886340534)
Notez que dans cet exemple, le tableau final a dtype
comme float
, pas int
, mais peut facilement (si nécessaire) être converti en int à l'aide de arr.astype(int)
La question de savoir comment gérer les données mixtes de genfromtxt
revient souvent. Les gens s'attendent à un tableau 2d et obtiennent à la place un 1d qu'ils ne peuvent pas indexer par colonne. C'est parce qu'ils obtiennent un tableau structuré - avec un type différent pour chaque colonne.
Tous les exemples du doc genfromtxt
le montrent:
>>> s = StringIO("1,1.3,abcde")
>>> data = np.genfromtxt(s, dtype=[('myint','i8'),('myfloat','f8'),
... ('mystring','S5')], delimiter=",")
>>> data
array((1, 1.3, 'abcde'),
dtype=[('myint', '<i8'), ('myfloat', '<f8'), ('mystring', '|S5')])
Mais permettez-moi de vous montrer comment accéder à ce type de données
In [361]: txt=b"""A, 1,2,3
...: B,4,5,6
...: """
In [362]: data=np.genfromtxt(txt.splitlines(),delimiter=',',dtype=('S1,int,float,int'))
In [363]: data
Out[363]:
array([(b'A', 1, 2.0, 3), (b'B', 4, 5.0, 6)],
dtype=[('f0', 'S1'), ('f1', '<i4'), ('f2', '<f8'), ('f3', '<i4')])
Mon tableau a donc 2 enregistrements (vérifiez la forme), qui sont affichés sous forme de tuples dans une liste.
Vous accédez à fields
par nom, pas par numéro de colonne (dois-je ajouter un lien de documentation de tableau structuré?)
In [364]: data['f0']
Out[364]:
array([b'A', b'B'],
dtype='|S1')
In [365]: data['f1']
Out[365]: array([1, 4])
Dans un cas comme celui-ci, cela pourrait être plus utile si je choisis un dtype
avec des "sous-réseaux". C'est un sujet dtype plus avancé
In [367]: data=np.genfromtxt(txt.splitlines(),delimiter=',',dtype=('S1,(3)float'))
In [368]: data
Out[368]:
array([(b'A', [1.0, 2.0, 3.0]), (b'B', [4.0, 5.0, 6.0])],
dtype=[('f0', 'S1'), ('f1', '<f8', (3,))])
In [369]: data['f1']
Out[369]:
array([[ 1., 2., 3.],
[ 4., 5., 6.]])
La colonne de caractères est toujours chargée en tant que S1
, mais les nombres sont maintenant dans un tableau à 3 colonnes. Notez qu'ils sont tous flottants (ou int).
In [371]: from scipy import stats
In [372]: stats.describe(data['f1'])
Out[372]: DescribeResult(nobs=2,
minmax=(array([ 1., 2., 3.]), array([ 4., 5., 6.])),
mean=array([ 2.5, 3.5, 4.5]),
variance=array([ 4.5, 4.5, 4.5]),
skewness=array([ 0., 0., 0.]),
kurtosis=array([-2., -2., -2.]))