web-dev-qa-db-fra.com

Comment utiliser numpy.genfromtxt lorsque la première colonne est une chaîne et que les colonnes restantes sont des nombres?

En gros, j'ai un tas de données où la première colonne est une chaîne (étiquette) et les colonnes restantes sont des valeurs numériques. Je lance le suivant:

data = numpy.genfromtxt('data.txt', delimiter = ',')

Cela lit bien la plupart des données, mais la colonne étiquette devient "nan". Comment puis-je gérer cela?

47
Jim

Par défaut, np.genfromtxt utilise dtype=float: c'est pourquoi vos colonnes de chaîne sont converties en NaN car, après tout, elles ne sont pas un nombre ... 

Vous pouvez demander à np.genfromtxt d'essayer de deviner le type réel de vos colonnes en utilisant dtype=None:

>>> from StringIO import StringIO
>>> test = "a,1,2\nb,3,4"
>>> a = np.genfromtxt(StringIO(test), delimiter=",", dtype=None)
>>> print a
array([('a',1,2),('b',3,4)], dtype=[('f0', '|S1'),('f1', '<i8'),('f2', '<i8')])

Vous pouvez accéder aux colonnes en utilisant leur nom, comme a['f0']...

Utiliser dtype=None est un bon truc si vous ne savez pas ce que devraient être vos colonnes. Si vous savez déjà quel type ils devraient avoir, vous pouvez donner une dtype explicite. Par exemple, dans notre test, nous savons que la première colonne est une chaîne, la seconde un int et nous voulons que la troisième soit un float. Nous utiliserions alors

>>> np.genfromtxt(StringIO(test), delimiter=",", dtype=("|S10", int, float))
array([('a', 1, 2.0), ('b', 3, 4.0)], 
      dtype=[('f0', '|S10'), ('f1', '<i8'), ('f2', '<f8')])

L'utilisation d'une dtype explicite est beaucoup plus efficace que d'utiliser dtype=None et est la méthode recommandée. 

Dans les deux cas (dtype=None ou explicite, non-homogène dtype), vous vous retrouvez avec un tableau structuré. 

[Remarque: avec dtype=None, l’entrée est analysée une seconde fois et le type de chaque colonne est mis à jour pour correspondre au type le plus large possible: nous essayons d’abord un bool, puis un int, puis un float, puis un complexe, puis nous gardons un chaîne si tout le reste échoue. L'implémentation est plutôt maladroite, en fait. Il y avait eu quelques tentatives pour rendre le type deviner plus efficace (en utilisant regexp), mais rien qui a collé jusqu'à présent]

56
Pierre GM

Si votre fichier de données est structuré comme ceci

col1, col2, col3
   1,    2,    3
  10,   20,   30
 100,  200,  300

alors numpy.genfromtxt peut interpréter la première ligne en tant qu'en-têtes de colonne à l'aide de l'option names=True. Avec cela, vous pouvez accéder aux données très facilement en fournissant l'en-tête de colonne:

data = np.genfromtxt('data.txt', delimiter=',', names=True)
print data['col1']    # array([   1.,   10.,  100.])
print data['col2']    # array([   2.,   20.,  200.])
print data['col3']    # array([   3.,   30.,  300.])

Puisque dans votre cas les données sont formées comme ceci

row1,   1,  10, 100
row2,   2,  20, 200
row3,   3,  30, 300

vous pouvez obtenir quelque chose de similaire en utilisant l'extrait de code suivant:

labels = np.genfromtxt('data.txt', delimiter=',', usecols=0, dtype=str)
raw_data = np.genfromtxt('data.txt', delimiter=',')[:,1:]
data = {label: row for label, row in Zip(labels, raw_data)}

La première ligne lit la première colonne (les étiquettes) dans un tableau de chaînes . La deuxième ligne lit toutes les données du fichier, mais supprime la première colonne . être utilisé de la même manière que le tableau structuré que numpy.genfromtxt crée à l'aide de l'option names=True:

print data['row1']    # array([   1.,   10.,  100.])
print data['row2']    # array([   2.,   20.,  200.])
print data['row3']    # array([   3.,   30.,  300.])
29
felerian

Vous pouvez utiliser numpy.recfromcsv(filename): les types de chaque colonne seront automatiquement déterminés (comme si vous utilisiez np.genfromtxt() avec dtype=None) et par défaut delimiter=",". Il s’agit essentiellement d’un raccourci pour np.genfromtxt(filename, delimiter=",", dtype=None) que Pierre GM a souligné dans sa réponse.

0

Pour un jeu de données de ce format:

CONFIG000   1080.65 1080.87 1068.76 1083.52 1084.96 1080.31 1081.75 1079.98
CONFIG001   414.6   421.76  418.93  415.53  415.23  416.12  420.54  415.42
CONFIG010   1091.43 1079.2  1086.61 1086.58 1091.14 1080.58 1076.64 1083.67
CONFIG011   391.31  392.96  391.24  392.21  391.94  392.18  391.96  391.66
CONFIG100   1067.08 1062.1  1061.02 1068.24 1066.74 1052.38 1062.31 1064.28
CONFIG101   371.63  378.36  370.36  371.74  370.67  376.24  378.15  371.56
CONFIG110   1060.88 1072.13 1076.01 1069.52 1069.04 1068.72 1064.79 1066.66
CONFIG111   350.08  350.69  352.1   350.19  352.28  353.46  351.83  350.94

Ce code fonctionne pour mon application:

def ShowData(data, names):
    i = 0
    while i < data.shape[0]:
        print(names[i] + ": ")
        j = 0
        while j < data.shape[1]:
            print(data[i][j])
            j += 1
        print("")
        i += 1

def Main():
    print("The sample data is: ")
    fname = 'ANOVA.csv'
    csv = numpy.genfromtxt(fname, dtype=str, delimiter=",")
    num_rows = csv.shape[0]
    num_cols = csv.shape[1]
    names = csv[:,0]
    data = numpy.genfromtxt(fname, usecols = range(1,num_cols), delimiter=",")
    print(names)
    print(str(num_rows) + "x" + str(num_cols))
    print(data)
    ShowData(data, names)

Sortie Python-2:

The sample data is:
['CONFIG000' 'CONFIG001' 'CONFIG010' 'CONFIG011' 'CONFIG100' 'CONFIG101'
 'CONFIG110' 'CONFIG111']
8x9
[[ 1080.65  1080.87  1068.76  1083.52  1084.96  1080.31  1081.75  1079.98]
 [  414.6    421.76   418.93   415.53   415.23   416.12   420.54   415.42]
 [ 1091.43  1079.2   1086.61  1086.58  1091.14  1080.58  1076.64  1083.67]
 [  391.31   392.96   391.24   392.21   391.94   392.18   391.96   391.66]
 [ 1067.08  1062.1   1061.02  1068.24  1066.74  1052.38  1062.31  1064.28]
 [  371.63   378.36   370.36   371.74   370.67   376.24   378.15   371.56]
 [ 1060.88  1072.13  1076.01  1069.52  1069.04  1068.72  1064.79  1066.66]
 [  350.08   350.69   352.1    350.19   352.28   353.46   351.83   350.94]]
CONFIG000:
1080.65
1080.87
1068.76
1083.52
1084.96
1080.31
1081.75
1079.98

CONFIG001:
414.6
421.76
418.93
415.53
415.23
416.12
420.54
415.42

CONFIG010:
1091.43
1079.2
1086.61
1086.58
1091.14
1080.58
1076.64
1083.67

CONFIG011:
391.31
392.96
391.24
392.21
391.94
392.18
391.96
391.66

CONFIG100:
1067.08
1062.1
1061.02
1068.24
1066.74
1052.38
1062.31
1064.28

CONFIG101:
371.63
378.36
370.36
371.74
370.67
376.24
378.15
371.56

CONFIG110:
1060.88
1072.13
1076.01
1069.52
1069.04
1068.72
1064.79
1066.66

CONFIG111:
350.08
350.69
352.1
350.19
352.28
353.46
351.83
350.94
0
mancoast