Seite 1 von 1

Daten-Suche

Verfasst: Sonntag 5. April 2009, 14:11
von ete
Hallo!

Ich habe ein Problem, beidem ich nicht weiterkomme:
Ich habe 2 Datensätze:

1)
CONTIG SEQUENZ
contig1 U35_12
contig1 U35_156
contig1 U35_89
contig2 U35_23
contig2 U35_9789

2)
SEQUENZ PVALUE
U35_12 568
U35_156 12
U35_89 79
U35_23 13
U35_9789 66

Ich möchte pro CONTIG die SEQUENZ mit dem niedrigsten PVALUE haben, also:

CONTIG SEQUENZ PVALUE
contig1 U35_156 12
contig2 U35_23 13

Ein weiteres Problem ist, dass der Datensatz ziemlich gross ist (2 x 51000 Zeilen). Ich wollte über eine SQlite3 Datenbank gehen aber alleine diese zu generieren dauert Stunden. Wie kann man sowas am Besten (und schnellesten) lösen? Über dict bräuchte man ja quasi ein dict im dict:

Code: Alles auswählen

 (d = {'contig1':('U35_12':568), ('U35_156':12)...})
Geht sowas?

Bin für jeden Hinweis dankbar!
Liebe Grüsse
Stefanie

Verfasst: Sonntag 5. April 2009, 14:36
von jerch
Mit einem solchem Dict könntest Du bei Deinem Datenvolumen schnell an die Grenzen Deiner Hardware stoßen, sprich der RAM geht Dir aus oder der Interpreter meckert über zu große Dicts (ist wiederum RAM beschränkt). Sind die "contig*"-Einträge relativ überschaubar, kannst Du das mit einem Dict lösen, ich würde aber als value nur den jeweils kleinsten gefunden Wert eintragen, also den value updaten, falls der neue kleiner ist als der im Dict befindliche.

Sollte selbst dieses Dict noch zu groß sein (für sehr viele "contig*"-Einträge), müßtest Du die Datensätze vorher auftrennen. Du könntest z.B. alle zu einem contig-gehörigen PVALUEs in ein tempfile schreiben und danach den kleinsten herausfischen.

Verfasst: Sonntag 5. April 2009, 14:56
von EyDu
Wenn das ganze offline laufen soll, würde ich einfach ein Dictionary mit den Minima anlegen und dann mit Brute-Force alle Zeilen vergleichen. Das dauert dann zwar ein paar Minuten, aber das ist immer noch schneller als eine effiziente Implementierung zu basteln.

Verfasst: Sonntag 5. April 2009, 17:07
von b.esser-wisser
Ich kann dir echt nicht glauben, dass 3MB Text in eine SQlite-Datenbank einfügen merklich dauert.
Deshalb hab ich dieses Programm zusammengehackt (und meine SQL-Kenntnisse aufgefrischt - ich mach das ja nicht total uneigennützig ;) )
Die drei Konstanten am Anfang müssten dann angepasst werden:
- CONTIG_SEQUENZ, SEQUENZ_PVALUE sind Dateiobjekte - z.B. mit open(), erzeugt.
- DBNAME ist der Dateiname für sqlite(), bei ":memory:" bleibt die Datenbank im RAM

hth, Jörg

Verfasst: Sonntag 5. April 2009, 18:20
von derdon
Warum importierst du itertools in der main-Funktion?

Verfasst: Sonntag 5. April 2009, 19:33
von b.esser-wisser
derdon hat geschrieben:Warum importierst du itertools in der main-Funktion?
:oops: Hab ich beim Aufräumen vor dem posten übersehen - bei meinen ersten Tests sahen die Test-Daten anders aus:

Code: Alles auswählen

#besser zum Experimentieren, aber unpraktisch:
TESTDATA = {
"CONTIG SEQUENZ":(
("contig1", "U35_12"),
("contig1", "U35_156"),
("contig1", "U35_89"),
("contig2", "U35_23"),
("contig2", "U35_9789"),
),
"SEQUENZ PVALUE":(
("U35_12", 568),
("U35_156", 12),
("U35_89", 79),
("U35_23", 13),
("U35_9789", 66),)}
(RegEx-search&replace sei dank ;) )

hth, Jörg

Verfasst: Montag 6. April 2009, 08:43
von ete
b.esser-wisser hat geschrieben: bei ":memory:" bleibt die Datenbank im RAM

hth, Jörg
Danke, das wusste ich nicht :D
Das hat mein Problem gelöst :wink:

Vielen Dank!
Stefanie

Verfasst: Montag 6. April 2009, 11:30
von ete
Hab noch ein Problem:

im Ganzen Datensatz wird nur ein Hit gefunden :?:
Picke ich mir aus dem Ganzen ein kleines Bespiel raus, wird dieses problemlos ausgeführt :?
Woran kann das liegen?
Hier mal die Daten:

http://www.snowflake-sl.info/posting/Python%20Fourm.rar

Wäre nett wenn jemand mal draufschauen könnte...Alles sehr merkwürdig oder ich seh den Wald vor lauter Bäumen nicht...

Danke

Verfasst: Montag 6. April 2009, 14:17
von b.esser-wisser
Ändere mal den letzten SQL-Query wie folgt:

Code: Alles auswählen

cursor = con.execute("""\
                     SELECT c.name, pvalue
                      FROM contigs AS c
                      JOIN sequence_pvalues AS sp
                       ON sequence
                      GROUP BY (c.name)
                     """)
... und wenn du die StringIO-Objecte durch "echte" file-Objekte ersetzt, brauchst du nicht mal 10000 Zeilen Müll in "unser" Programm kopieren, sondern kannst deine Textdateien verwenden.

hth, Jörg

Verfasst: Montag 6. April 2009, 15:02
von ete
b.esser-wisser hat geschrieben:brauchst du nicht mal 10000 Zeilen Müll in "unser" Programm kopieren, sondern kannst deine Textdateien verwenden.

hth, Jörg
Hab ich vergessen rausszuschmeissen, sorry.

Danke, es tut sich was (Rechner rechnet noch). Kannst du bitte kurz erklären warum er nur einen Hit gefunden hat?

@Edit:

Dasselbe Ergbnis mit verändertem Code. Wieder nur ein Hit :?:

Lg

Verfasst: Montag 6. April 2009, 17:02
von b.esser-wisser
Bei mir geht's aber (der Satz ist mal ein echter Klassiker :lol: ).
Weil es tatsächlich ein bisschen zu lang dauert, habe ich mal einen Index eingebaut: Dieses Programm braucht bei mir ca. 6s, wenn die Datenbank erstellt wird (2s wenn sie wiederverwendet wird). Einfach die beiden .txt-Dateien aus deinem Archiv in den selben Ordner kopieren und starten.

hth, Jörg

Verfasst: Montag 6. April 2009, 17:09
von ete
Oh, vielen Dank das funktioniert!
Konnte von deinem Code viel Lernen! Danke!

Liebe Grüsse und schönen Feierabend!
Stefanie

Verfasst: Mittwoch 8. April 2009, 11:27
von ete
Hallo!

Hab doch noch ein Problem:
Jetzt sucht er den mittleren Wert heraus. Bsp.

(u'Contig9913', u'U35_33989', 0.223)
(u'Contig9913', u'U35_37449', 0.81600000000000006)
(u'Contig9913', u'U35_16441', 0.78300000000000003)

ergibt:
Contig9913, 0.783000

Danke nochmal.
Stefanie

:!: Edit:

Sorry hat sich erledigt. War mein Fehler :wink:

OT: Shell-Lösung

Verfasst: Mittwoch 8. April 2009, 13:50
von lutz.horn
Ein Vorschlag, der nichts mit Python zu tun hat:

Code: Alles auswählen

#!/bin/sh

cat CONTIG_SEQUENZ  | cut -f1 -d" " | sort -u |
while read contig
do
    join CONTIG_SEQUENZ SEQUENZ_PVALUE -1 2 | grep $contig | sort -k 3 -n | head -1
done
Für die jeweils 50.000 Zeilen großen Dateien CONTIG_SEQUENZ und SEQUENZ_PVALUE benötigt dieses Skript auf meiner Maschine ca. 6 Sekunden.

Der Kern dieser Lösung ist der zweckmäßige Einsatz von join und sort