2012-12-11 3 views
0

J'essaie d'extraire des données d'un grand fichier CSV dans le format suivant, en supposant que 'x' est une donnée sous forme de texte ou d'entier. Chaque groupe a un identifiant unique, mais n'a pas toujours le même nombre de lignes par regroupement ou couleur. Les données sont séparées de la couleur par une virgule.Python pour extraire et trier les données d'un fichier

id, x 
red, x 
green, x 
blue, x 
black, x 

id, x 
yellow, x 
green, 
blue, x 
black, x 

id, x 
red, x 
green, x 
blue, x 
black, x 

id, x 
red, x 
green, x 
blue, x 

id, x 
red, x 
green, x 
blue, x 
black, x 

Je souhaite réorganiser les données dans un format de colonne. L'ID doit être la première colonne et toutes les données séparées par une virgule. Mon but est de lire le premier mot de la ligne et de le placer dans la colonne appropriée.

line 0 - ID - red - green - blue - yellow - black 
line 1 - x, x, x, , x, 
line 2 - , x, x, x, x, 
line 3 - x, x, x, , x, 
line 4 - x, x, x, , , 
line 5 - x, x, x, , x, 

C'est ce que je cherchais ...

readfile = open("db-short.txt", "r") 
datafilelines = readfile.readlines() 

writefile = open("sample.csv", "w") 

temp_data_list = ["",]*7 
td_index = 0 

for line_with_return in datafilelines: 
    line = line_with_return.replace('\n','') 
    if not line == '': 
     if not (line.startswith("ID") or 
       line.startswith("RED") or 
       line.startswith("GREEN") or 
       line.startswith("BLUE") or 
       line.startswith("YELLOW") or 
       line.startswith("BLACK")): 
      temp_data_list[td_index] = line 
      td_index += 1 

      temp_data_list[6] = line 
     if (line.startswith("BLACK") or line.startswith("BLACK")): 
      temp_data_list[5] = line 
     if (line.startswith("YELLOW") or line.startswith("YELLOW")): 
      temp_data_list[4] = line 
     if (line.startswith("BLUE") or line.startswith("BLUE")): 
      temp_data_list[3] = line 
     if (line.startswith("GREEN") or line.startswith("GREEN")): 
      temp_data_list[2] = line 
     if (line.startswith("RED") or line.startswith("RED")): 
      temp_data_list[1] = line 
     if (line.startswith("ID") or line.find("ID") > 0): 
      temp_data_list[0] = line 
    if line == '': 
     temp_data_str = "" 
     for temp_data in temp_data_list: 
      temp_data_str += temp_data + "," 
     temp_data_str = temp_data_str[0:-1] + "\n" 
     writefile.write(temp_data_str) 

     temp_data_list = ["",]*7 
     td_index = 0 

if temp_data_list[0]: 
    temp_data_str = "" 
    for temp_data in temp_data_list: 
     temp_data_str += temp_data + "," 
    temp_data_str = temp_data_str[0:-1] + "\n" 
    writefile.write(temp_data_str) 
readfile.close() 
writefile.close() 
+1

Qu'avez-vous essayé jusqu'à présent? Le module 'csv' de la librairie standard est probablement un bon point de départ. –

+0

Je sais que vous avez dit que vous vouliez une solution python mais avez-vous considéré R? Il a été construit pour ces sortes de tâches – Stedy

+0

je confesss Je suis nouveau à la programmation et j'essayé d'utiliser cette ... http://ubuntuforums.org/showpost.php?p=6159649&postcount=4 Mais je continuais obtenir cette erreur. IndexError: indice d'affectation de liste hors de portée Maintenant, je l'ai appris est à cause de la façon dont les données sont formatées je vais jeter un oeil à R –

Répondre

1

Cela suppose Python < 2.7 (et ne prend donc pas avantage d'ouvrir plusieurs fichiers avec un with, écrivant les en-têtes avec le haut -a writeheaders, etc. Notez que pour le faire fonctionner correctement, j'ai enlevé les espaces entre les virgules dans votre CSV.Comme mentionné parJamesHenstridge, il serait certainement intéressant de lire sur le module csv de sorte que cela fait un peu plus de sens

import csv 

with open('testfile', 'rb') as f: 
    with open('outcsv.csv', 'wb') as o: 
    # Specify your field names 
    fieldnames = ('id', 'red', 'green', 'blue', 'yellow', 'black') 

    # Here we create a DictWriter, since your data is suited for one 
    writer = csv.DictWriter(o, fieldnames=fieldnames) 

    # Write the header row 
    writer.writerow(dict((h, h) for h in fieldnames)) 

    # General idea here is to build a row until we hit a blank line, 
    # at which point we write our current row and continue 
    new_row = {} 
    for line in f.readlines(): 
     # This will split the line on a comma/space combo and then 
     # Strip off any commas/spaces that end a word 
     row = [x.strip(', ') for x in line.strip().split(', ')] 
     if not row[0]: 
     writer.writerow(new_row) 
     new_row = {} 
     else: 
     # Here we write a blank string if there is no corresponding value; 
     # otherwise, write the value 
     new_row[row[0]] = '' if len(row) == 1 else row[1].strip() 

    # Check new_row - if not blank, it hasn't been written (so write) 
    if new_row: 
     writer.writerow(new_row) 

Utilisation de vos données ci-dessus (avec quelques nombres séparés par des virgules aléatoires jetés), ce écrit:

id,red,green,blue,yellow,black 
x,"2,8","2,4",x,,x 
x,,,"4,3",x,x 
x,x,x,x,,x 
x,x,x,x,, 
x,x,x,x,,x 
+0

vous manque le début d'une instruction 'if' dans l'instruction' for' ? –

+0

@JamesHenstridge Ha ouais, aucune idée de comment cela n'a pas été collé. Je vais mettre à jour un peu, merci de le signaler. – RocketDonkey

+0

Il y a des espaces aléatoires entre le texte et la virgule, y a-t-il un moyen de le faire détecter les espaces et de les supprimer? –

Questions connexes