2013-01-06 2 views
0

J'essaye d'écrire un code pour convertir CSV en ARFF. J'importer les valeurs entre chaque "," à une cellule d'un tableau, par exemple une instance telle que:Comment trouver le type de tableau

Monday,176,49,203,27,77,38,Second 

est converti en:

['Monday', '176', '49', '203', '27', '77', '38', 'Second'] 

Le problème est que Python reconnaît chaque cellule sous forme de chaîne et vous pouvez voir les types reconnus par Python pour l'exemple:

[<type 'str'>, <type 'str'>, <type 'str'>, <type 'str'>, <type 'str'>, <type 'str'>, <type 'str'>, <type 'str'>] 

Je cherche un moyen de distinguer entre les attributs nominaux et numériques?

+1

Avez-vous essayé? http: // stackoverflow.com/questions/354038/how-do-i-check-if-a-string-is-a-number-in-python – 808sound

Répondre

2
for i in lst: 
    try: 
     int(i) 
     #whatever you want to do 
    except ValueError: 
     #error handling 

qui fonctionnera, bien que de ce serait beaucoup mieux:

for i in lst: 
    if i[-1].isdigit(): #it is a number 
     #whatever 
    else: 
     #whatever else 

Taken de here

Voir aussi: str.isdigit() method

+0

Merci - avec cette méthode tout va bien sauf la dernière cellule qui est reconnue comme chaîne –

+1

@UNSWCSE n'est pas "Second" une chaîne? – Volatility

+0

désolé, il est reconnu comme le numéro –

1

Si la performance est beaucoup ici, je J'essaierai d'adopter une approche en trois étapes. Cette approche évite inutilement de lancer une chaîne à int ou float, puis d'échouer en utilisant une simple vérification du premier caractère.

  • Pour chaque morceau, vérifiez si le premier caractère est un chiffre ou non
  • Dans ce cas, essayez d'abord l'analyser comme int et si elle échoue, l'analyser comme float
  • Si tout cela échoue , vous avez un gros problème :)

Quelque chose comme:

for chunk in chunks: 
    if chunk[0].isdigit(): 
     try: 
      return int(chunk) 
     except ValueError: 
      return float(chunk) 
    else: 
     # It's a string (a non-numeric entity) 
     return chunk 

Yo Vous aurez bien sûr besoin d'un traitement un peu plus spécial pour supporter les littéraux hex/oct dans le fichier texte/csv mais je ne pense pas que ce soit un cas normal pour vous?

EDIT: Venez y penser, Volatility a utilisé une approche similaire avec la seule différence appeler isdigit sur la chaîne entière au lieu de simplement le premier caractère. Cela peut prendre un peu plus de temps si nous avons de longues séquences numériques dans lesquelles isdigit est appelé sur chaque char tandis que mon approche vérifie toujours le premier caractère, ce qui pourrait être un peu plus rapide.

3

Le mieux que je peux penser est quelque chose comme ça, en utilisant ast.literal_eval:

import ast 

def converter(x): 
    try: 
     val = ast.literal_eval(x) 
     return val 
    except ValueError: 
     return x 

qui donne

>>> seq = ['Monday', '176', '49', '203', '27', '77', '38', 'Second'] 
>>> newseq = [converter(x) for x in seq] 
>>> newseq 
['Monday', 176, 49, 203, 27, 77, 38, 'Second'] 
>>> map(type, newseq) 
[<type 'str'>, <type 'int'>, <type 'int'>, <type 'int'>, <type 'int'>, <type 'int'>, <type 'int'>, <type 'str'>] 

L'avantage d'utiliser ast.literal_eval est qu'il gère plus de cas dans une belle façon:

>>> seq = ['Monday', '12.3', '(1, 2.3)', '[2,"fred"]'] 
>>> newseq = [converter(x) for x in seq] 
>>> newseq 
['Monday', 12.3, (1, 2.3), [2, 'fred']] 
+0

Une bonne solution s'il est nécessaire de prendre en charge les littéraux hexadécimaux, les types de tuple etc. dans le fichier texte, mais un OMI un peu trop lourd si le fichier texte contient du texte et des nombres simples. Pourtant, +1 –

+0

Eh bien, les solutions 'isdigit' échoueront sur les nombres négatifs, ou n'importe quoi avec un' + ', etc., donc ISTM nous pourrions aussi bien utiliser le builtin. – DSM

+0

Je peux toujours changer le 'isdigit' pour vérifier le dernier chiffre, ça marchera toujours – Volatility

Questions connexes