dictonaries problem

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
mit
User
Beiträge: 285
Registriert: Dienstag 16. September 2008, 10:00

Hallo,
ich habe folgende Eingabe Datei:

Code: Alles auswählen

G|G0024s00480|s_24|G0024s00480.1|438189|438579|-1
G|G0024s00240|s_24|G0024s00240.1|14401|16599|1
G|G0022s00500|s_22|G0022s00500.1|990172|990304|1
G|G0023s00620|s_23|G0023s00620.1|708242|709405|-1
Und versuche die Daten aus der Datei in dictonary zu speichern

Code: Alles auswählen

{ 's_22': {'G0022s00500.1': ['990172', '990304', '1']},
  's_23': {'G0023s00620.1': ['708242', '709405', '-1']},
  's_24': {'G0024s00240.1': ['14401', '16599', '1']}}
Leider wird die erste Zeile aus der Datei in dictonary durch die zweite Zeile überschrieben und ich erhalte nicht die gewünschte Ausgabe:

Code: Alles auswählen

{ 's_22': {'G0022s00500.1': ['990172', '990304', '1']},
  's_23': {'G0023s00620.1': ['708242', '709405', '-1']},
  's_24': {'G0024s00240.1': ['14401', '16599', '1']},
	   'G0024s00480.1': ['438189','438579','-1']}}
Ich habe dieses skript geschrieben:

Code: Alles auswählen

import pprint

def retrieveIds():
  f = open("a.txt","r")
  linkageGroups = {}
  while True:
    line = f.readline().rstrip()
  
    if not line:
      break
    
    line = line.split("|")
    #G|G0024s00480|s_24|G0024s00480.1|438189|438579|-1
    #0       1      2      3             4     5    6

    linkageId = line[2] # s_24
    gId       = line[3] # G0024s00240.1
    start     = line[4] # 14401
    end       = line[5] # 16599
    strand    = line[6] # -1
    
    aGroup = {gId:[start, end, strand]} 

    linkageGroups[linkageId] = aGroup

      
  pp = pprint.PrettyPrinter(indent=2)
  pp.pprint(linkageGroups)
  

if __name__ == '__main__':
  seqLen = 0
  firstSeqRead = False
  setNewLine = False
  
  retrieveIds()
Was mache ich falsch?

Viele Grüße
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Deine 3. Zeile ist eben kein brauchbarer Dictionary Key, da er mehrfach vorkommt.
Je nachdem was du benoetigst, kannst du dein Dict von Dicts in ein Dict von Listen von Dicts abaendern oder ein Multidict benutzen, aber beschreib am besten erstmal was genau du benoetigst.
mit
User
Beiträge: 285
Registriert: Dienstag 16. September 2008, 10:00

s_24 kommt in der Datei zweimal vor und deshalb wollte ich zwei dicts erstellen um diese Information zu speichern:
G0024s00480.1|438189|438579|-1
G0024s00240.1|14401|16599|1
wobei:
G0024s00480.1
G0024s00240.1
als Schlüssel dienen sollten.

Später wollte ich die folgende Ausgabe erhalten:
s_22, G0022s00500.1, 990172, 990304, 1
s_23, G0023s00620.1, 708242, 709405, -1
s_24, G0024s00240.1, 14401, 16599, 1
s_24, G0024s00480.1, 438189, 438579, -1

Und auf die 3 letzten werte zugreifen können.

Leider weiss ich nicht wie man es am besten macht.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

mit hat geschrieben:s_24 kommt in der Datei zweimal vor und deshalb wollte ich zwei dicts erstellen um diese Information zu speichern:
Was macht das für einen Sinn zwei Dicts mit jeweils einem Schlüssel zu erstellen? Nimm doch ein Dictionary jeweils mit den Werten als Schlüssel.

Das ganze Packst du dann noch in ein 2. Dictionary und fertig(ich nehme für sowas immer ein defaultdict).

Code: Alles auswählen

from collections import defaultdict
...
def retrieveIds(): 
    ...
    linkageGroups = defaultdict(dict)
    for line in f: 
        linkageId, gId, start, end, strand = line.rstrip().split("|")[2:]
        linkageGroups[linkageId][gId] = [start, end, strand]
PS: Es ist übrigens immer nett, die Datei hinterher zu schließen, wenn man fertig ist.
mit
User
Beiträge: 285
Registriert: Dienstag 16. September 2008, 10:00

Danke es funktioniert, aber ich noch zwei Fragen:

1.) Wie bekommt man folgende Ausgabe?
s_22, G0022s00500.1, 990172, 990304, 1
s_23, G0023s00620.1, 708242, 709405, -1
s_24, G0024s00240.1, 14401, 16599, 1
s_24, G0024s00480.1, 438189, 438579, -1

2.) Wie könnte man z.B. in einer for-Schleife eine if-Anweisung nutzen um "-1" abfangen und z.B. auf diese Werte zugreifen 708242 und 709405?

Der aktuelle Kode sieht wie folgt aus:

Code: Alles auswählen

import pprint
from collections import defaultdict
  
def retrieveIds():
  f = open("a.txt","r")
  linkageGroups = defaultdict(dict) 

  for line in f:
    #G|G0024s00480|s_24|G0024s00480.1|438189|438579|-1
    #0       1      2      3             4     5    6
    linkageId, gId, start, end, strand = line.rstrip().split("|")[2:]
    linkageGroups[linkageId][gId] = [start, end, strand]
        
  pp = pprint.PrettyPrinter(indent=2)
  pp.pprint(linkageGroups)
  print "\n\n"
  print (linkageGroups)
  print "\n\n"
  print (linkageGroups["s_24"]["G0024s00480.1"])
  print (linkageGroups["s_24"]["G0024s00480.1"][0])
  print (linkageGroups["s_24"])
  
if __name__ == '__main__':
  retrieveIds()
Und die Eingabe Datei sieht wie folgt aus:

Code: Alles auswählen

G|G0024s00480|s_24|G0024s00480.1|438189|438579|-1
G|G0024s00240|s_24|G0024s00240.1|14401|16599|1
G|G0022s00500|s_22|G0022s00500.1|990172|990304|1
G|G0023s00620|s_23|G0023s00620.1|708242|709405|-1 
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Was für eine Art von Daten ist das? Für Python gibt es viele Zusatzmodule im Internet, auch für wissenschaftliche Zwecke. Gut möglich, dass dir so etwas besser helfen könnte.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

mit hat geschrieben:1.) Wie bekommt man folgende Ausgabe?
s_22, G0022s00500.1, 990172, 990304, 1
s_23, G0023s00620.1, 708242, 709405, -1
s_24, G0024s00240.1, 14401, 16599, 1
s_24, G0024s00480.1, 438189, 438579, -1
Indem du die einzelnen Einträge mit einer for-Schleife durchgehst und dann deine Ausgabe machst
mit
User
Beiträge: 285
Registriert: Dienstag 16. September 2008, 10:00

Leider gibt es dafür kein Python Modul und ich bin mit der folgenden for-Schleife gescheitert:

Code: Alles auswählen

  for a, b in linkageGroups.items():
    print (a, b)
und erhalte diese Ausgabe:

Code: Alles auswählen

('s_24', {'G0024s00240.1': ['14401', '16599', '1'], 'G0024s00480.1': ['438189', '438579', '-1']})
('s_22', {'G0022s00500.1': ['990172', '990304', '1']})
('s_23', {'G0023s00620.1': ['708242', '709405', '-1']})
Wie muss die for-Schleife aussehen?
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

mit hat geschrieben:Leider gibt es dafür kein Python Modul
Natürlich nicht, warum sollte es auch für dein spezielles Problem ein extra Modul in der Standardbibliothek geben?
und ich bin mit der folgenden for-Schleife gescheitert:
Nein du bist nicht gescheitert, du hast einfach nur das Beispiel aus dem Tutorial abgeschrieben und dich gewundert warum das nicht das ist was du willst. Ich helfe gerne aber ein bisschen Eigeninitiative erwarte ich auch. Zum Lösung vorkauen ist mir meine Zeit zu schade und du lernst dabei auch nichts.
mit
User
Beiträge: 285
Registriert: Dienstag 16. September 2008, 10:00

Habe es mit zwei for-Schleifen geschafft

Code: Alles auswählen

  for a, b in linkageGroups.items():
    for c, d in b.items():
      print a + ", " + c + ", " + d[0] + ", " + d[1] + ", " + d[2]
Ist dies eine gute Lösung?
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Ja, allerdings würde dir von solch kryptischen Variablennamen abraten. Zu der Ausgabe selbst, wenn man irgendwas stupide wiederholen muss(in deinem Fall die ganzen ", ") ist das immer ein Hinweis darauf, dass es auch kürzer geht.

Code: Alles auswählen

print ", ".join([a, c] + d)
Übrigens sind dictionaries unsortiert wenn man z.B. nach Schlüsseln sotieren will, wäre ein

Code: Alles auswählen

for key in sorted(dictionary):
    print key, dictionary[key]
am einfachsten.
BlackJack

@Darii: Von der Standardbibliothek war ja nicht die Rede. Für viele Formate gibt es halt schon Module von Drittanbietern. Speziell wenn man nicht der erste ist, der sich mit einem bestimmten Format befasst.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

BlackJack hat geschrieben:@Darii: Von der Standardbibliothek war ja nicht die Rede. Für viele Formate gibt es halt schon Module von Drittanbietern. Speziell wenn man nicht der erste ist, der sich mit einem bestimmten Format befasst.
Siehe Kontext meines Satzes. Es ging um den Umgang mit Schleifen.
BlackJack

@Darii: Wenn Du's darauf beschränken möchtest -- für mich ging's hier um das Verarbeiten dieser Daten.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich habe das in Bezug zu meiner Frage gesehen. Dummerweise ist die Antwort leider nicht auf das Wesentliche ("welche Art Daten?") eingangen, sondern hat sich auf ein "nee, gibt's nicht..." beschränkt. Da kann man dann natürlich auch nicht mehr viel machen.
Antworten