Seite 1 von 1
Daten schneller einlesen
Verfasst: So Jul 23, 2017 12:11 pm
von jessi
Hallo zusammen,
ich habe vielleicht eine etwas komische Frage, bin aber leider in Google bzw. diversen Skripten nicht recht viel schlauer geworden. Ich habe wirklich sehr sehr viele Messdaten. Diese einzulesen dauert nun sehr lange bzw. kommt als R-Meldung
Error: cannot allocate vector of size xxx Mb. Gibt es eine Lösung, die Messdaten ev. "schneller" einzulesen bzw. meinen memory.size zu erhöhen um überhaupt mit den vielen Messdaten Auswertungen zu machen?
Mein bisheriger Code:
Code: Alles auswählen
library(RSQLite)
m <- dbDriver("SQLite")
con <- dbConnect(m, dbname = "messdaten"')
alltables <- dbListTables(con)
alltables
# bei dieser Zeile kommt dann nach einiger Zeit die oben beschriebene Fehlermeldung
daten <- dbGetQuery(con, 'SELECT datum a r e v FROM data_wind')
Ich hab mal gelesen, dass man Matrizen (mit Null befüllt) vorher schon definierten sollte, da dies den Einleseprozess beschleunigen soll. Die Matrix mit den Messdaten würde ich wie folgt definieren:
Leider weiß ich die genau Größe (col & row) der Matrix "daten" nicht, da diese von der Zeit abhängt, also mal lese ich die Daten von 5 Tagen ein, dann wieder von 17 Tagen bzw. nur von einem.
Gibt es vielleicht noch andere Möglichkeiten oder ist die Methode der Nullmatrix die ich hier mal als ev. Lösung annehme überhaupt richtig.
Vielen Lieben dank für Lösungsvorschläge,
J
Re: Daten schneller einlesen
Verfasst: So Jul 23, 2017 3:07 pm
von student
Hallo Jessi,
ich denke, Du hast ein Speicherplatzproblem. Kannst Du die Daten sequenziell einlesen? Schau mal
hier!
Re: Daten schneller einlesen
Verfasst: So Jul 23, 2017 4:21 pm
von jessi
Hallo Student,
vielen Dank für deine Antwort. Ich habe jetzt folgendes probiert:
Code: Alles auswählen
library(RODBC)
library(ff)
library(ETLUtils)
x <- read.dbi.ffdf(query = "SELECT * FROM data", dbConnect.args = list(drv = dbDriver("SQLite"), dbname = 'messdaten'),VERBOSE=TRUE)
Output
Code: Alles auswählen
ffdf (all open) dim=c(1656994,10), dimorder=c(1,2) row.names=NULL
ffdf virtual mapping
PhysicalName VirtualVmode PhysicalVmode AsIs VirtualIsMatrix PhysicalIsMatrix PhysicalElementNo
Zeitstempel Zeitstempel integer integer FALSE FALSE FALSE 1
Datum Datum integer integer FALSE FALSE FALSE 2
Stunde Stunde integer integer FALSE FALSE FALSE 3
Minute Minute integer integer FALSE FALSE FALSE 4
p p integer integer FALSE FALSE FALSE 5
l l integer integer FALSE FALSE FALSE 6
v v integer integer FALSE FALSE FALSE 7
u u integer integer FALSE FALSE FALSE 8
w w integer integer FALSE FALSE FALSE 9
g g integer integer FALSE FALSE FALSE 10
PhysicalFirstCol PhysicalLastCol PhysicalIsOpen
Zeitstempel 1 1 TRUE
Datum 1 1 TRUE
Stunde 1 1 TRUE
Minute 1 1 TRUE
p 1 1 TRUE
l 1 1 TRUE
v 1 1 TRUE
u 1 1 TRUE
w 1 1 TRUE
g 1 1 TRUE
ffdf data
Zeitstempel Datum Stunde Minute p l v u
1 201703130000 20170313 0 0 47 7 0
2 201703130000 20170313 0 0 47 8 0
3 201703130000 20170313 0 0 47 9 3
4 201703130000 20170313 0 0 47 10 24
: : : : : : : : :
165695 201703152355 20170315 23 55 57 14 7
165696 201703152355 20170315 23 55 57 15 10
165697 201703152355 20170315 23 55 57 16 36
165698 201703152355 20170315 23 55 57 17 14
165699 201703152355 20170315 23 55 57 18 2
w g
1
2
3
4
5
6
7
8
: : :
165692
165693
165694
165695
165696
165697
165698
165699
Leider werde ich aus dem Output nicht so recht schlau. Werden jetzt alle Daten eingelesen und kann ich diese "normal" weiter bearbeiten oder muss ich zusätzlich was berücksichtigen?
Wenn ich die Daten weiter bearbeite, beispielsweise.
bekomme ich eine
Code: Alles auswählen
ffdf (all open) dim=c(165699,0), dimorder=c(1,2) row.names=NULL
ffdf virtual mapping
[1] PhysicalName VirtualVmode PhysicalVmode AsIs VirtualIsMatrix
[6] PhysicalIsMatrix PhysicalElementNo PhysicalFirstCol PhysicalLastCol PhysicalIsOpen
<0 Zeilen> (oder row.names mit Länge 0)
ffdf data
[1] "[empty matrix]"
Ich glaube auch, dass die Werte als factor rausgeschrieben werden?
glg.
Jess
Re: Daten schneller einlesen
Verfasst: So Jul 23, 2017 7:46 pm
von EDi
Wie student schon schrieb hast du ein Speicherplatzproblem.
Wenn die 'weiterverarbeitung' nur aus subsets etc besteht, würde ich das auf der Datenbank machen und nicht in R (in SQL wäre das ein WHERE ).
Für DB-R interaktionen gibt es auch das neue/überarbeitetet DBI package.
Re: Daten schneller einlesen
Verfasst: So Jul 23, 2017 8:12 pm
von jessi
Hallo.
Leider besteht die Weiterverarbeitung nicht nur aus subset-Abfragen. Allerdings scheitere ich schon beim Einlesen der Daten. Gibt es sonst keine Möglichkeit viele Daten einzulesen?
mfg. jess
Re: Daten schneller einlesen
Verfasst: Mo Jul 24, 2017 9:21 am
von jogo
Hallo Jessi,
jessi hat geschrieben: So Jul 23, 2017 12:11 pm
ich habe vielleicht eine etwas komische Frage, bin aber leider in Google bzw. diversen Skripten nicht recht viel schlauer geworden. Ich habe wirklich sehr sehr viele Messdaten. Diese einzulesen dauert nun sehr lange bzw. kommt als R-Meldung
Error: cannot allocate vector of size xxx Mb. Gibt es eine Lösung, die Messdaten ev. "schneller" einzulesen bzw. meinen memory.size zu erhöhen um überhaupt mit den vielen Messdaten Auswertungen zu machen?
Hier wird dieses Problem breit diskutiert:
https://stackoverflow.com/questions/517 ... -size-n-mb
Eine Kurzversion, die die möglichen Lösungen beschreibt ist:
Mein bisheriger Code:
Code: Alles auswählen
library(RSQLite)
m <- dbDriver("SQLite")
con <- dbConnect(m, dbname = "messdaten"')
alltables <- dbListTables(con)
alltables
# bei dieser Zeile kommt dann nach einiger Zeit die oben beschriebene Fehlermeldung
daten <- dbGetQuery(con, 'SELECT datum a r e v FROM data_wind')
Ich hab mal gelesen, dass man Matrizen (mit Null befüllt) vorher schon definierten sollte, da dies den Einleseprozess beschleunigen soll. Die Matrix mit den Messdaten würde ich wie folgt definieren:
Diese Lösung ("preallocation of a matrix/vector") trifft für Dich nicht zu.
preallocation ist immer dann hilfreich, wenn ansonsten ein Vektor (bzw. eine Matrix) Stück für Stück aufgebaut (und dabei ständig vergrößert) wird. In Deinem Fall bekommst Du durch die Datenbankabfrage einen kompletten Dataframe.
Neben allem, was schon geschrieben wurde, könnte es noch die Möglichkeit geben, möglichst viel Arbeit schon auf der Seite der Datenbank zu erledigen:
a) also entweder direkt in SQLite oder
b) in einer anderen Datenbank (dafür müssen die Daten natürlich erst migriert werden).
Dort müsste mindestens eine Stufe der Aggregation der Daten erfolgen, um die Datenmenge zu reduzieren.
Folgende Fragen nebenbei:
Wieviel RAM hat Dein Computer?
Welches Betriebssystem verwendest Du? (insbesondere 32-bit oder 64-bit?)
Welche Version von R verwendest Du? (auch hier wieder: insbesondere 32-bit oder 64-bit?)
Gruß, Jörg
Re: Daten schneller einlesen
Verfasst: Mo Jul 24, 2017 2:05 pm
von jessi
Hallo zusammen,
vielen Dank für eure Antworten. Ich probiere jetzt einen anderen Zugang und zwar die Daten schon vor der query-Abfrage entsprechend zu filtern. Leider geht das auch nur mit R, da ich keinen direkten Zugriff auf die db habe.
Das ganze möchte ich jetzt mitteln for-Schleifen machen und ich muss gestehen, vor lauter R blicke ich nicht mehr durch.
Ich brauche insgesamt drei for-Schleifen, da ich drei Bedingungen an die Daten stelle (die Datumszuweisung, Längen- und Breitengrade).
Das ganze habe ich jetzt mal so zu lösen versucht.
Code: Alles auswählen
#sql einlesen
library(RSQLite)
m <- dbDriver("SQLite")
con <- dbConnect(m, dbname = "messdaten"')
alltables <- dbListTables(con)
alltables
#Einschränken der Daten
for (Tag in c('20140101', '20140113', '20140131')) {
for (p in subset(48, 53))
for (l in subset(8, 15))
daten <- paste("SELECT p, l, v",
"FROM data",
"WHERE (Tag = Tag)",
"AND (p = p)",
"AND (l = l)"}
Irgendwo hab ich aber einen Denkfehler drinnen, beim Schleifenbau. Als Fehlermeldung bekomme ich
Code: Alles auswählen
Fehler: Unerwartete(s) '}' in:
" "AND (p = p)",
"AND (l = l)"}"
Ich muss nochmals um eure Hilfe bitte
Danke vielmals. Jess
Re: Daten schneller einlesen
Verfasst: Mo Jul 24, 2017 9:37 pm
von EDi
Das sieht mir viel zu kompliziert aus... Liest dich bitte noch ein wenig in SQL ein (das Problem hat wenig mit R zu tun): da gibt es ein 'IN' operator...
Re: Daten schneller einlesen
Verfasst: Di Jul 25, 2017 8:35 am
von jogo
Hallo Jessi,
jessi hat geschrieben: Mo Jul 24, 2017 2:05 pm
Irgendwo hab ich aber einen Denkfehler drinnen, beim Schleifenbau. Als Fehlermeldung bekomme ich
Code: Alles auswählen
Fehler: Unerwartete(s) '}' in:
" "AND (p = p)",
"AND (l = l)"}"
es muss am Ende heißen:
"AND (l = l)")} (die schließende runde Klamme ist das Gegenstück zu der öffnenden beim Aufruf der Funktion
paste )
Gruß, Jörg
Re: Daten schneller einlesen
Verfasst: Mi Jul 26, 2017 2:22 pm
von jessi
Hallo.
Jetzt habe ich noch was anderes probiert:
Code: Alles auswählen
i <- dbGetQuery(con, 'SELECT datum, a, r, e, v, FROM wind WHERE data_wind in datum (20140401) AND p = :x AND range = :y', params = list(x=seq(48,53), y = seq(1800,2200,200)))
Hier funktioniert die letzte Abfrage y=seq(1800,2200,200) nicht. Gibt es hier einen Trick, wie ich R sage, dass y eine Schrittweite von 200 hat?
Danke für eure Mithilfe!!
Jessi