2017-11-02 4 views
3

Ich bin neu in Python und ich habe Probleme mit der Verwendung von Listen.Bestimmen Sie den Datentyp von CSV - Python

Ich mein Problem, wie Sie sehen können, habe ich eine datos.csv-Datei mit der folgenden Struktur.

1,4.0,?,?,none,? 
2,2.0,3.0,?,none,? 
2,2.5,2.5,?,tc,39 

Mit dieser Funktion speichere ich die Daten in einer Liste.

def main(): 
    lista = [] 
    with open('datos.csv','r') as f: 
     for line in f: 
      lista.append(line.strip().split(',')) 
    determinar_tipo(lista) 

if __name__ == '__main__': 
    main() 

Bis zu diesem Punkt habe ich kein Problem. Das Problem kommt jedoch, wenn ich den Typ der Elemente bestimmen muss.

diesen Code verwenden, die ich in Spalten meiner Liste organisieren

for columna in itertools.izip(*lista): 

Dieser Code mir die Daten als Spalten behandeln können, wie angegeben, hier ist ein Beispiel dafür, was ich von diesem receibe ‚für‘:

{'1','2','2'} 
{'4.0','2.0','2.5'} 
     . 
     . 
     . 

Wie Sie die gleichen Daten aus meiner cSV-Datei, sondern Struktur von Spalten sehen.

Ok, hier ist mein Problem.

Ich muss den Typ jeder der Spalten basierend auf ihrem Argument bestimmen, dh angenommen, dass die erste Spalte {'1', '2', '3'} das erste Element und dieses Element überprüft der Typ dieser Spalte, in diesem Fall wäre der Typ dieser Spalte int.

Ein anderes Beispiel mit {'4.0', '2', '2.5'}, ich überprüfe den Typ des primären Elements und bestimme, dass es float ist.

Für den Fall {'?', '?' , '?'} der Typ wäre "unbestimmt".

Das Problem kommt jedoch mit den Zeichen '?', Wenn ich ein Symbol von diesen bekomme, muss ich das nächste Element der Spalte überprüfen, es wäre das Element 'Wort', {'?', 'Wort', '5'}, so dass der Typ der Spalte string ist.

Dies ist der Code, den ich entwickelt habe, um es zu verifizieren, aber ich habe die Typen nicht korrekt ermittelt.

def determinar_tipo(lista): 
    b = 0 
    aux = [] 

    for columna in itertools.izip(*lista): 
    if columna[0] != "?": #If it's a number or string I save it 
     aux.append(columna[0]) 
     print columna[0] 
    else:     #If it's '?' 
     if len(columna) > b: 
     b = b + 1 
     if columna[b] != "?": 
      aux.append(columna[b]) 
      b = 0 
     else: 
      b = b + 1 
      print b 
    #Correct code 
    for x in aux: 
    try: 
     var_type = type(int(x)) 
    except ValueError: 
     try: 
     var_type = type(float(x)) 
     except ValueError: 
     var_type = type(x) 
    print var_type 

Der erste Teil des Codes ist in einer anderen Liste zum Speichern des Elements verantwortlich, die Art für jede der Spalten, um zu bestimmen, während der zweite Teil des Codes zum Prüfen des Typs jedes dieser Elemente ist verantwortlich in der vorherigen Liste.

Zusammengefasst, ich weiß nicht, wie man das 'for' zurückgibt das richtige Element, um den Typ der Spalte korrekt überprüft werden.

Dies ist die richtige Antwort für meine Daten:

1 , 4.0 , ? ,  ?   , none , ? 
2 , 2.0 , 3.0 ,  ?   , none , ? 
2 , 2.5 , 2.5 ,  ?   , tc , 39 
int float float  undetermined  string  int** 
+0

Gibt es einen Grund, dass 1, 2, 2 ist ein int? Es könnte eine Kategorie sein, die zufällig ein Int ist, könnte es nicht (angesichts der Anzahl der verschiedenen Werte)? Oder sind nur Strings jemals Kategorien? –

+0

Wenn es eine Zahl ohne Dezimalzahlen ist, wird es 'int' sein, wenn Sie Dezimalstellen haben, wird es 'float', wenn es ein Wort wie 'none' ist wird vom 'string' Typ sein und wenn in der ganzen Spalte nur '?' wir müssen angeben, dass es vom 'unbestimmten' Typ ist – fiticida

+0

Der Versuch, den Typ aus einer Menge von Werten zu bestimmen, ist ziemlich schwierig, da es tausend Fälle geben kann, die Sie berücksichtigen müssen. Zum Beispiel, wenn eine Spalte ist (2, 3.5, 4) 'sollte es ein' float' sein? Muss ich dann jedes Element in jeder Spalte überprüfen? Ich würde vorschlagen, die Typinformation in die Titelzeile einzuschließen und dann die Informationen entsprechend zu analysieren. – Adirio

Antwort

2

ich die fucntions Namen geändert, so dass sie mehr Sinn machen:

def determinar_tipo(valor): 
    if valor == '?': 
     return 'undetermined' 
    try: 
     int(valor) 
    except ValueError: 
     pass 
    else: 
     return int 
    try: 
     float(valor) 
    except ValueError: 
     return str 
    else: 
     return float 

def determinar_tipos(lista): 
    aux = [] 
    for columna in itertools.izip(*lista): 
     i = 0 
     while i < len(columna) and columna[i] == '?': 
      i += 1 
     aux.append(columna[i]) 
    for i, each in enumerate(aux): 
     aux[i] = determinar_tipo(each) 
    return aux 
+0

Oh, es funktioniert perfekt, Danke !!! – fiticida

2

ich diesen Ansatz gemacht. Der wichtige Teil ist der Generator.Lassen Sie mich wissen, ob es hilfreich ist:

import itertools 

lista =[ 
    ['1','4.0','?','?','none','?'], 
    ['2','2.0','3.0','?','none','?'], 
    ['2','2.5','2.5','?','tc','39'] 
] 
def columnType(column): 
    for val in column: 
     if val != '?': 
      try: 
       float(val) 
       if '.' in val: yield 'float' 
       else: yield 'int' 
      except ValueError: 
       yield 'string' 

for columna in itertools.izip(*lista): 
    print columna, next(columnType(columna),'undetermined') 

als Ergebnis geben:

('1', '2', '2') int 
('4.0', '2.0', '2.5') float 
('?', '3.0', '2.5') float 
('?', '?', '?') undetermined 
('none', 'none', 'tc') string 
('?', '?', '39') int 

EDIT: Alternative Funktion mit @ MaartenFabré Vorschlag:

import itertools 

lista =[ 
    ['1','4.0','?','?','none','?'], 
    ['2','2.0','3.0','?','none','?'], 
    ['2','2.5','2.5','?','tc','39'] 
] 

def columnType(column): 
    for val in column: 
     if val != '?': 
      try: 
       float(val) 
       if '.' in val: return 'float' 
       else: return 'int' 
      except ValueError: 
       return 'string' 
    return 'undetermined' 


for columna in itertools.izip(*lista): 
    print columna, columnType(columna) 
+1

Wenn Sie nur einen Wert aus dem 'columnType' verwenden, warum' yield' verwenden? –

+0

Richtig, es funktioniert perfekt, danke Kumpel. Es war sehr hilfreich! – fiticida

+0

@ MaartenFabré Ich möchte es bis zum ersten gültigen Auftreten durchlaufen. Mit einem Generator kann ich das erreichen. 'next (columna), 'unbestimmt')' gibt mir das erste gültige Vorkommen von 'columnType (columna)' und wenn es nicht gefunden werden kann, gibt es mir den Fallback ''unbestimmt''. – FcoRodr

Verwandte Themen