2012-08-13 19 views
12

Próbuję przeanalizować szereg plików tekstowych i zapisać je jako pliki CSV przy użyciu Python (2.7.3). Wszystkie pliki tekstowe mają 4-wierszowy nagłówek, który musi zostać usunięty. Linie danych mają różne ograniczniki, w tym "(quote), - (dash),: kolumna i puste miejsce. Zauważyłem, że jest to trudne, aby zakodować go w C++ z wszystkimi różnymi ogranicznikami, więc postanowiłem wypróbować to w Pythonie, słysząc to. jest stosunkowo łatwiejsze w porównaniu do C/C++Pliku pliku tekstowego z Python

Napisałem kawałek kodu, aby przetestować go dla pojedynczego wiersza danych i działa, ale nie udało mi się zrobić go dla rzeczywistego pliku. Wygląda na to, że moja obecna implementacja odczytuje plik tekstowy jako listę i nie ma metody zamiany dla obiektu listy:

Będąc nowicjuszem w Pythonie Utknąłem w tym momencie, każdy sygnał wejściowy byłby doceniany!

Dzięki!

# function for parsing the data 
def data_parser(text, dic): 
for i, j in dic.iteritems(): 
    text = text.replace(i,j) 
return text 

# open input/output files 

inputfile = open('test.dat') 
outputfile = open('test.csv', 'w') 

my_text = inputfile.readlines()[4:] #reads to whole text file, skipping first 4 lines 


# sample text string, just for demonstration to let you know how the data looks like 
# my_text = '"2012-06-23 03:09:13.23",4323584,-1.911224,-0.4657288,-0.1166382,-0.24823,0.256485,"NAN",-0.3489428,-0.130449,-0.2440527,-0.2942413,0.04944348,0.4337797,-1.105218,-1.201882,-0.5962594,-0.586636' 

# dictionary definition 0-, 1- etc. are there to parse the date block delimited with dashes, and make sure the negative numbers are not effected 
reps = {'"NAN"':'NAN', '"':'', '0-':'0,','1-':'1,','2-':'2,','3-':'3,','4-':'4,','5-':'5,','6-':'6,','7-':'7,','8-':'8,','9-':'9,', ' ':',', ':':',' } 

txt = data_parser(my_text, reps) 
outputfile.writelines(txt) 

inputfile.close() 
outputfile.close() 
+2

Powinieneś załączyć kopię pliku, który chcesz przeanalizować i oczekiwany wynik, w ten sposób łatwiej ci będzie pomóc. –

Odpowiedz

10

Chciałbym użyć for pętli iteracyjne nad linii w pliku tekstowego:

for line in my_text: 
    outputfile.writelines(data_parser(line, reps)) 

Jeśli chcesz odczytać pliku linia po linii, zamiast ładowania całość u początek skryptu można zrobić coś takiego:

inputfile = open('test.dat') 
outputfile = open('test.csv', 'w') 

# sample text string, just for demonstration to let you know how the data looks like 
# my_text = '"2012-06-23 03:09:13.23",4323584,-1.911224,-0.4657288,-0.1166382,-0.24823,0.256485,"NAN",-0.3489428,-0.130449,-0.2440527,-0.2942413,0.04944348,0.4337797,-1.105218,-1.201882,-0.5962594,-0.586636' 

# dictionary definition 0-, 1- etc. are there to parse the date block delimited with dashes, and make sure the negative numbers are not effected 
reps = {'"NAN"':'NAN', '"':'', '0-':'0,','1-':'1,','2-':'2,','3-':'3,','4-':'4,','5-':'5,','6-':'6,','7-':'7,','8-':'8,','9-':'9,', ' ':',', ':':',' } 

for i in range(4): inputfile.next() # skip first four lines 
for line in inputfile: 
    outputfile.writelines(data_parser(line, reps)) 

inputfile.close() 
outputfile.close() 
+0

dzięki! Jaki byłby najlepszy sposób na pominięcie pierwszych 4 linii? Przyznać, nie mogłem znaleźć sposobu, aby to zrobić, dlatego zdecydowałem się przeczytać całość. Czy powinienem zapisać plik z wyjątkiem pierwszych 4 wierszy do innego pliku, aby uruchomić pętlę powyżej? Założę się, że powinien być łatwiejszy sposób. EDYCJA: och, czekaj, myślę, że masz na myśli zastąpienie linii 'txt = data_parser (mój_tekst, powtórzenia)' z pętlą, którą masz powyżej. – marillion

+0

Pominięto już pierwsze 4 wiersze za pomocą linii 'my_text = plik_wejściowy.readlines() [4:] ', jeśli wolisz czytać plik wiersz po wierszu i nie ładować całej rzeczy do pamięci RAM na początku skryptu, mogę zaktualizować moją odpowiedź. –

+0

Przepraszam, źle zrobiłem na pierwszym miejscu (zobacz moje EDIT powyżej), ale dzięki, działa idealnie !!! Teraz byłbym bardzo zadowolony, gdyby dowiedziałem się o sposobie robienia "linii odczytu-parsowania-zapisu linii (linia po linii)". Mam kilka dużych plików o wielkości + 500 MB, które mogą zepsuć rzeczy. Czy mógłbyś zaktualizować swoją odpowiedź drugim przykładem? – marillion

2

Istnieje kilka sposobów, aby przejść o tym. Jedną opcją byłoby użycie inputfile.read() zamiast inputfile.readlines() - musisz napisać osobny kod, aby usunąć pierwsze cztery wiersze, ale jeśli chcesz, aby ostateczne wyjście było w postaci pojedynczego ciągu, to może to mieć największy sens.

Drugą, prostszą opcją byłoby ponowne dołączenie ciągów po usunięciu pierwszych czterech linii za pomocą my_text = ''.join(my_text). Jest to trochę mało wydajne, ale jeśli prędkość nie jest głównym problemem, kod będzie najprostszy.

Na koniec, jeśli rzeczywiście chcesz, aby dane wyjściowe były listą ciągów znaków zamiast pojedynczego łańcucha, możesz po prostu zmodyfikować analizator składni danych, aby można było iterować po liście. To może wyglądać tak:

def data_parser(lines, dic): 
    for i, j in dic.iteritems(): 
     for (k, line) in enumerate(lines): 
      lines[k] = line.replace(i, j) 
    return lines 
10

od przyjętych odpowiedzi, wygląda na to żądane zachowanie jest włączenie

skip 0 
skip 1 
skip 2 
skip 3 
"2012-06-23 03:09:13.23",4323584,-1.911224,-0.4657288,-0.1166382,-0.24823,0.256485,"NAN",-0.3489428,-0.130449,-0.2440527,-0.2942413,0.04944348,0.4337797,-1.105218,-1.201882,-0.5962594,-0.586636 

do

2012,06,23,03,09,13.23,4323584,-1.911224,-0.4657288,-0.1166382,-0.24823,0.256485,NAN,-0.3489428,-0.130449,-0.2440527,-0.2942413,0.04944348,0.4337797,-1.105218,-1.201882,-0.5962594,-0.586636 

Jeśli to prawda, to myślę, podobnie jak

import csv 

with open("test.dat", "rb") as infile, open("test.csv", "wb") as outfile: 
    reader = csv.reader(infile) 
    writer = csv.writer(outfile, quoting=False) 
    for i, line in enumerate(reader): 
     if i < 4: continue 
     date = line[0].split() 
     day = date[0].split('-') 
     time = date[1].split(':') 
     newline = day + time + line[1:] 
     writer.writerow(newline) 

byłby nieco prostszy niż rzeczy z reps.

+0

Próbowałem użyć modułu csv przed wydaniem bitu 'reps', ale odkryłem, że dokumentacja jest trochę zagmatwana. Twój przykład wyraźnie wyjaśnia. Spróbuję tego, również ze względu na naukę. 1. czy eliminujesz cytaty w pliku tekstowym przez 'quoting = False'? 2. Czy mógłbyś zweryfikować moje zrozumienie? Linia 'date' w kodzie najpierw dzieli część daty i sama staje się listą,' day' i 'time' są następnie dzielone, a reszta linii jest dołączana do' dnia' i 'czasu'. Nie jestem pewien, jak automatycznie dodaje się przecinki w linii 'newline = day + time + line [1]'. Hmm ... – marillion

+0

@marillon: (1) Tak, istnieje wiele różnych opcji cytowania. Sądzę, że to trochę dziwne, w zasadzie, pozbyć się ich wszystkich, ale może z jakiegoś powodu tego potrzebujesz. (2) Tak. Przecinki nie są dodawane w 'nowej linii' - to tylko lista. 'writerow' to metoda' write', która dodaje przecinki do wyjściowego ciągu znaków (lub tabulatorów lub jakiegokolwiek innego separatora, jakiego chcieliśmy) i obsługiwałaby cytowanie, gdybyśmy tego chcieli. – DSM

+0

Ok, myślę, że mam to. Ponadto nigdy nie trzeba było parsować części danych linii, ponieważ była ona już oddzielona przecinkiem. Dobra informacja, wielkie dzięki! – marillion

Powiązane problemy