unterschiedliche Anzahl von Zeilen aus Datei ziehen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
conva
User
Beiträge: 4
Registriert: Donnerstag 26. August 2010, 16:06

Hallo,
ich bin neu hier und auch in Python bin ich noch recht unerfahren.
Ich versuche mein Problem mal anhand eines Minimalbeispiels zu erklären:
Datei 1 hat eine Tabelle mit x Zeilen und y Spalten:
243 100110100
422 011100101
643 101000110
823 100010010
425 011000100
1075 100110100
1154 111011010
Datei 2 sieht folgendermaßen aus:
243 643 3
422 643 2
643 643 1
823 823 1
425 1075 2
1075 1075 1
1154 1154 1
Die erste Zahlen in den ersten Spalten stimmen überein. Ich möchte nun für jede Zeile eine Datei schreiben, in der genauso viele Zeilen aus Datei 1 stehen wie in Spalte 3 von Datei 2 angegeben. Für jede Zeile würde ich spontan eine for Schleife schreiben, aber da stört die unregelmäßige Anzahl an Zeilen die ich jeweils raus ziehen möchte. Vielleicht ist auch was mit einer if Abfrage möglich (wenn Zahl in Spalte 1 in beiden Dateien übereinstimmen, dann ziehe soviel Zeilen raus wie in Spalte 3 genannt :K )?
Für mein Minimalbeispiel sähen die gewünschten Ausgabedateien folgendermaßen aus:
hier sieben Zeilen in Datei 1- also sieben Dateien:
erste:
243 100110100
422 011100101
643 101000110

zweite:
422 011100101
643 101000110

dritte:
643 101000110

vierte:
823 100010010

fünfte:
425 011000100
1075 100110100

sechste:
1075 100110100

siebte:
1154 111011010

Wäre toll wenn jemand eine Idee hätte wie ich das Problem lösen kann. Vielen Dank schonmal im Voraus

P.S.: Die Dateien sind natürlich wesentlich größer. Ich habe meinen Code hier nicht reingestellt, weil das nur ein Teilproblem darstellt. Es wird noch transponiert, zusammengefasst, gerechnet,.....
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo und willkkommen im Forum!

Zeig doch mal, was du bereit an Code dafür geschrieben hast. Damit lässt sich sicher arbeiten. Außerdem müsstest du noch genauer spezifizieren, was du mit "große Dateien" meinst.

Sebastian
Das Leben ist wie ein Tennisball.
conva
User
Beiträge: 4
Registriert: Donnerstag 26. August 2010, 16:06

große Dateien heißt, dass die reinen .txt Dateien über 80 und 5MB groß sind.
Hier mal der entscheidende Teil aus dem Code den ich schon geschrieben habe

Einlesen der Dateien mit readlines()

Code: Alles auswählen

f_out=open('ausgabe.txt','w')
li1=[]

gts_split=lines1[0].rstrip().split(',')[2:]
for g in xrange(len(gts_split)):
	li1.append(gts_split[g]) #Namen aus erster Spalte
	li1[g]+='      '                #Leerzeichen sind noetig fuer Weiterverwendung in anderem Programm

for i in xrange(1,len(lines1)):
	split1=re.split(',',lines1[i].rstrip())[2:]
	for j in xrange(len(split1)):
		li1[j]+=split1[j]

result=transposed2(li1) #Werte werden transponiert
for zeile in li1:
	f_out.write('%s\n'%zeile)
f_out.close()
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ok, das sieht ja ein wenig nach Chaos aus bei dir... Ich mache mal einen Vorschlag:

Code: Alles auswählen

>>> spam = """243 100110100
... 422 011100101
... 643 101000110
... 823 100010010
... 425 011000100
... 1075 100110100
... 1154 111011010"""
>>> eggs = """243 643 3
... 422 643 2
... 643 643 1
... 823 823 1
... 425 1075 2
... 1075 1075 1
... 1154 1154 1"""
>>> def parse_spam(row):
...     x, y = row.split()
...     return int(x), y
... 
>>> def parse_eggs(row):
...     return map(int, row.split())
... 
>>> foo = map(parse_spam, spam.splitlines())
>>> bar = map(parse_eggs, eggs.splitlines())
>>> baz = dict((row[0], index) for (index, row) in enumerate(foo))
>>> for elem, _, count in bar:
...     start = baz[elem]
...     print foo[start:start+count]
... 
[(243, '100110100'), (422, '011100101'), (643, '101000110')]
[(422, '011100101'), (643, '101000110')]
[(643, '101000110')]
[(823, '100010010')]
[(425, '011000100'), (1075, '100110100')]
[(1075, '100110100')]
[(1154, '111011010')]
Das Leben ist wie ein Tennisball.
conva
User
Beiträge: 4
Registriert: Donnerstag 26. August 2010, 16:06

ja so sehen leider alle meine Skripte aus: Chaos pur :oops: Aber ich lerne ja noch...

Das Beispiel funktioniert, aber wenn ich das auf die echten Daten anwende, bekomme ich folgende Fehlermeldung:

foo = map(parse_spam, spam.splitlines())
AttributeError: 'list' object has no attribute 'splitlines'

Ich hab den Fehler gegoogelt aber keine passende Antwort gefunden, zumindest keine die ich verstehe.
In den echten Datensätzen haben die Spalten noch Überschriften. Kann das evtl. zu Problemen führen?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Dann scheint dein `spam` eben schon eine Liste zu sein und nicht wie bei EyDu ein String, d.h. du kannst `.splitlines()` streichen.
conva
User
Beiträge: 4
Registriert: Donnerstag 26. August 2010, 16:06

und der nächste Fehler:

Traceback (most recent call last):
File "tscan_pipe2.py", line 30, in <module>
foo = map(parse_spam, spam)
File "tscan_pipe2.py", line 25, in parse_spam
x,y=row.split()
ValueError: need more than 1 value to unpack

ich hab `.splitlines()`gestrichen

hier noch mal kurz der Code:

Code: Alles auswählen

import re

f=open('Datei1.txt')
spam=f.readlines()[:100]
f.close()

f=open('Datei2.txt')
eggs=f.readlines()
f.close()

f_out=open('Ausgabe.txt','w')
li1=[]

def parse_spam(row):
	x,y=row.split()
	return int(x),y
def parse_eggs(row):
	return map(int, row.split())

foo = map(parse_spam, spam)
bar = map(parse_eggs, eggs)
bez=dict((row[0],index) for(index,row) in enumerate(foo))
for elem, _, count in bar:
	start=baz[elem]
	print foo[start:start+count]

f_out.close()				
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Schluss mit dem Cargo-Cult-Programmieren!
Du solltest Snippets nur verwenden, wenn du sie verstehst.

Deine Daten unterscheiden sich erheblich von EyDu's Daten, deine liegen als Listen vor, seine als String.

`split` trennt den String an dem uebergebenen Trennzeichen in Listen auf - per default bei jedem whitespace-Zeichen.

Du hast zwei Moeglichkeiten: Du aenderst das Einlesen der Daten und veraenderst sie dort gleich zur gewuenschten Form, oder du fuegst sie erst wieder zu einem String zusammen.

Fuer 1:

Code: Alles auswählen

with open("Datei.txt") as f:
    foo = list()
    for _ in xrange(100):
        line = f.readline().split()
        x, y = line.split(maxsplit=1)
        foo.append(int(x), y)
with open("Datei2.txt") as f:
    bar = list()
    for line in f:
        values = [int(x) for x in line.split()]
        bar.extend(values)
Antworten