CSV Stapelverarbeitung mit Filterfunktion für große Datenmengen
Hallo,
Ich studiere und muss in einer Projektarbeit Daten auswerten, die mir leider nur in vielen (über 100000) csv Dateien vorliegen. Obwohl meine Aufgabe die Auswertung ist, benötige ich ewig bzw. teilweise ist es gar nicht möglich die Daten zusammenzufassen.
Ich habe bereits ein Skript, welches für die meisten Datensätze funktioniert, doch gibt es auch Datensätze bei denen ich über 7 Gb CSV Dateien verarbeiten muss, hierfür habe ich zu wenig Arbeitsspeicher.
Mein Skript funktioniert bisher so, dass ich erst alles in den Arbeitsspeicher lade und am Ende eine neue CSV Datei erzeuge. Im Zweiten Schritt wird diese dann wieder eingelesen und anhand eines Aktualitätskriteriums (Modification TimeStamp) gefiltert und doppelte Einträge gelöscht.
Das Problem ist, dass bei CSV Beständen (8gb) weit mehr als 32 gb Arbeitsspeicher verbraucht werden.
Ich benötige nun ein Skript, welches einen Datenpool anlegt und bei jeder neu eingelesenen CSV Datei prüft ob diese Datenzeile im Pool vorhanden ist. Wenn dieser älter ist, soll diese Datenzeile nicht in dem Pool hinzugefügt werden. Wenn die Datenzeile neuer ist soll diese hinzugefügt werden und die alte Datenzeile im Pool gelöscht werden. Dadurch kann ich die Speicherbelastung umgehen, da oftmals aus 8 gb Rohdaten nur noch wenige 100 Mb übrig bleiben, da identische Datenzeilen sehr häufig vorliegen.
Hier ein Bearbeitungschema:
Ich bitte um Hilfe. Mir fehlt die Zeit um mich derartig tiefgreifend in PowerShell einzuarbeiten.
Ich bin auch bereit per PayPal den Aufwand zu entlohnen einfach eine PN.
VG
Rippchen
Ich studiere und muss in einer Projektarbeit Daten auswerten, die mir leider nur in vielen (über 100000) csv Dateien vorliegen. Obwohl meine Aufgabe die Auswertung ist, benötige ich ewig bzw. teilweise ist es gar nicht möglich die Daten zusammenzufassen.
Ich habe bereits ein Skript, welches für die meisten Datensätze funktioniert, doch gibt es auch Datensätze bei denen ich über 7 Gb CSV Dateien verarbeiten muss, hierfür habe ich zu wenig Arbeitsspeicher.
# Schritt 1: Einlesen der CSV Dateien
workflow MergeCSV {
param([string]$path)
# Dateien die verarbeitet werden ermitteln
$files = Get-ChildItem -Path $path -File -Recurse -Filter '*.csv'
#Funktion die eine CSV entsprechend bearbeitet und modifiziert zurückgibt
function Process-CSV($file){
$content = Get-Content -Path $file.FullName | select -skip 7
return ($content[0..($content.GetUpperBound(0)-1)] | ConvertFrom-CSV -Delimiter ";" -Header "Colour","Car","TimeStamp","Note","PublicationTimeStamp","ModificationTimeStamp" | select -Property 'Car','ID',@{n='TimeStamp';e={get-date -Date $_.Timestamp -Format 'dd-MM-yyyy HH:mm:ss'}},'Note',@{n='PublicationTimeStamp';e={get-date -Date $_.PublicationTimeStamp -Format 'dd-MM-yyyy HH:mm:ss'}},@{n='ModificationTimeStamp';e={get-date -Date $_.ModificationTimeStamp -Format 'dd-MM-yyyy HH:mm:ss'}})
}
foreach -parallel -throttle 8 ($csv in $files){
# rufe Funktion zum Bearbeiten der CSV-Datei in Parallelverarbeitung auf
Process-CSV -file $csv
}
}
$CSV_PATH = 'C:\Daten Bearbeitung\Import'
$outVW = 'C:\Daten Bearbeitung\Export\VW.csv'
$outAudi= 'C:\Daten Bearbeitung\Export\Audi.csv'
$outVWred = 'C:\Daten Bearbeitung\Export\VWred.csv'
$outVWblue = 'C:\Daten Bearbeitung\Export\VWblue.csv'
$outAudired= 'C:\Daten Bearbeitung\Export\Audired.csv'
$outAudiblue= 'C:\Daten Bearbeitung\Export\Audiblue.csv'
MergeCSV -path $CSV_PATH | select "Car","Colour","TimeStamp","Note","PublicationTimeStamp","ModificationTimeStamp" | group {$_.Car} | %{
$group = $_.group
switch ($_.Name){
'VW'{
$group | ?{$_."Colour" -eq 'red'} | export-csv -Path $outVWred -NoTypeInformation -Encoding "UTF8" -Delimiter ";" -Append
$group | ?{$_."Colour" -eq 'blue'} | export-csv -Path $outVWblue -NoTypeInformation -Encoding "UTF8" -Delimiter ";" -Append
$group | export-csv -Path $outVW -NoTypeInformation -Encoding "UTF8" -Delimiter ";" -Append
}
'Audi'{
$group | ?{$_."Colour" -eq 'red'} | export-csv -Path $outAudired -NoTypeInformation -Encoding "UTF8" -Delimiter ";" -Append
$group | ?{$_."Colour" -eq 'blue'} | export-csv -Path $outAudiblue -NoTypeInformation -Encoding "UTF8" -Delimiter ";" -Append
$group | export-csv -Path $outAudi -NoTypeInformation -Encoding "UTF8" -Delimiter ";" -Append
}
} $group | export-csv -Path $out -NoTypeInformation -Encoding "UTF8" -Delimiter ";" -Append
}
# Schritt 2: Doppelte Wert anhand der Aktuallität aussortieren
workflow FILTERCSV
{
Parallel
{
gci 'C:\Daten Bearbeitung\Export\VWred.csv'| %{
gc $_.FullName | select -Skip 1| ConvertFrom-CSV -Delimiter ";" -Header "Colour","Car","TimeStamp","Note","PublicationTimeStamp","ModificationTimeStamp" | group {get-date $_.TimeStamp}| %{$_.Group | sort {get-date $_.'ModificationTimeStamp'} -Descending | select -First 1} | Sort "TimeStamp", "ModificationTimeStamp" -descending | export-csv 'C:\Daten Bearbeitung\Export\bereinigte Daten\VWred.csv' -Append -Delimiter ";" -Notype -Encoding UTF8
}
gci 'C:\Daten Bearbeitung\Export\VWblue.csv'| %{
gc $_.FullName | select -Skip 1| ConvertFrom-CSV -Delimiter ";" -Header "Colour","Car","TimeStamp","Note","PublicationTimeStamp","ModificationTimeStamp" | group {get-date $_.TimeStamp}| %{$_.Group | sort {get-date $_.'ModificationTimeStamp'} -Descending | select -First 1} | Sort "TimeStamp", "ModificationTimeStamp" -descending | export-csv 'C:\Daten Bearbeitung\Export\bereinigte Daten\VWblue.csv' -Append -Delimiter ";" -Notype -Encoding UTF8
}
gci 'C:\Daten Bearbeitung\Export\Audired.csv'| %{
gc $_.FullName | select -Skip 1| ConvertFrom-CSV -Delimiter ";" -Header "Colour","Car","TimeStamp","Note","PublicationTimeStamp","ModificationTimeStamp" | group {get-date $_.TimeStamp}| %{$_.Group | sort {get-date $_.'ModificationTimeStamp'} -Descending | select -First 1} | Sort "TimeStamp", "ModificationTimeStamp" -descending | export-csv 'C:\Daten Bearbeitung\Export\bereinigte Daten\Audired.csv' -Append -Delimiter ";" -Notype -Encoding UTF8
}
gci 'C:\Daten Bearbeitung\Export\Audiblue.csv'| %{
gc $_.FullName | select -Skip 1| ConvertFrom-CSV -Delimiter ";" -Header "Colour","Car","TimeStamp","Note","PublicationTimeStamp","ModificationTimeStamp" | group {get-date $_.TimeStamp}| %{$_.Group | sort {get-date $_.'ModificationTimeStamp'} -Descending | select -First 1} | Sort "TimeStamp", "ModificationTimeStamp" -descending | export-csv 'C:\Daten Bearbeitung\Export\bereinigte Daten\Audiblue.csv' -Append -Delimiter ";" -Notype -Encoding UTF8
}
}
}
FILTERCSV
# Schritt 3: Zusammenfassen der Daten
workflow Zusammenfassen {
param([string]$path)
# Dateien die verarbeitet werden ermitteln
$files = Get-ChildItem -Path $path -File -Recurse -Filter '*.csv'
#Funktion die eine CSV entsprechend bearbeitet und modifiziert zurückgibt
function Process-CSV($file){
return Get-Content -Path $file.FullName | select -skip 1 | ConvertFrom-CSV -Delimiter ";" -Header "Colour","Car","TimeStamp","Note","PublicationTimeStamp","ModificationTimeStamp" )
}
foreach -parallel -throttle 8 ($csv in $files){
# rufe Funktion zum Bearbeiten der CSV-Datei in Parallelverarbeitung auf
Process-CSV -file $csv
}
}
$CSV_PATH = 'C:\Daten Bearbeitung\Export\bereinigte Daten'
$out = 'C:\Daten Bearbeitung\Export\bereinigte Daten\Gesamt\BEGesamt.csv'
$outVW = 'C:\Daten Bearbeitung\Export\bereinigte Daten\Gesamt\BEVW.csv'
$outAudi= 'C:\Daten Bearbeitung\Export\bereinigte Daten\Gesamt\BEAudi.csv'
Zusammenfassen -path $CSV_PATH | select "Car","Colour","TimeStamp","Note","PublicationTimeStamp","ModificationTimeStamp" | group {$_.Car} | %{
$group = $_.group
switch ($_.Name){
'VW'{
$group | export-csv -Path $outVW -NoTypeInformation -Encoding "UTF8" -Delimiter ";" -Append
}
'Audi'{
$group | export-csv -Path $outAudi -NoTypeInformation -Encoding "UTF8" -Delimiter ";" -Append
}
} $group | export-csv -Path $out -NoTypeInformation -Encoding "UTF8" -Delimiter ";" -Append
}
Mein Skript funktioniert bisher so, dass ich erst alles in den Arbeitsspeicher lade und am Ende eine neue CSV Datei erzeuge. Im Zweiten Schritt wird diese dann wieder eingelesen und anhand eines Aktualitätskriteriums (Modification TimeStamp) gefiltert und doppelte Einträge gelöscht.
Das Problem ist, dass bei CSV Beständen (8gb) weit mehr als 32 gb Arbeitsspeicher verbraucht werden.
Ich benötige nun ein Skript, welches einen Datenpool anlegt und bei jeder neu eingelesenen CSV Datei prüft ob diese Datenzeile im Pool vorhanden ist. Wenn dieser älter ist, soll diese Datenzeile nicht in dem Pool hinzugefügt werden. Wenn die Datenzeile neuer ist soll diese hinzugefügt werden und die alte Datenzeile im Pool gelöscht werden. Dadurch kann ich die Speicherbelastung umgehen, da oftmals aus 8 gb Rohdaten nur noch wenige 100 Mb übrig bleiben, da identische Datenzeilen sehr häufig vorliegen.
Hier ein Bearbeitungschema:
Ich bitte um Hilfe. Mir fehlt die Zeit um mich derartig tiefgreifend in PowerShell einzuarbeiten.
Ich bin auch bereit per PayPal den Aufwand zu entlohnen einfach eine PN.
VG
Rippchen
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 322625
Url: https://administrator.de/forum/csv-stapelverarbeitung-mit-filterfunktion-fuer-grosse-datenmengen-322625.html
Ausgedruckt am: 27.04.2025 um 23:04 Uhr
8 Kommentare
Neuester Kommentar
Hallo,
Gruß,
Peter
Zitat von @Rippchen:
Ich studiere und muss in einer Projektarbeit Daten auswerten, die mir leider nur in vielen (über 100000) csv Dateien vorliegen. Obwohl meine Aufgabe die Auswertung ist, benötige ich ewig bzw. teilweise ist es gar nicht möglich die Daten zusammenzufassen.
Die einzelnen CSV Dateien sind vom Aufbau identisch?Ich studiere und muss in einer Projektarbeit Daten auswerten, die mir leider nur in vielen (über 100000) csv Dateien vorliegen. Obwohl meine Aufgabe die Auswertung ist, benötige ich ewig bzw. teilweise ist es gar nicht möglich die Daten zusammenzufassen.
denen ich über 7 Gb CSV Dateien verarbeiten muss
Wie lang ist ein Datensatz bzw. um wie viele Datensätze geht es denn?Aktualitätskriteriums (Modification TimeStamp) gefiltert und doppelte Einträge gelöscht.
Pro Datensatz oder pro CSV Datei?Ich bitte um Hilfe. Mir fehlt die Zeit um mich derartig tiefgreifend in PowerShell einzuarbeiten.
Ist es eine Option die Datenmengen in eine Datenbank (SQL Express, MYSQL, MariaDB, ... (MS-Access)) zu packen und dort die Duplicate erst gar nicht einzulesen oder in einen 2ten Schritt dort zu entfernen, und deine Auswertung mit den Daten aus der Datenbank zu füttern anstatt diese nicht gerade kleinen Mengen direkt in Powershell bzw. im RAM bearbeiten zo wollen?Gruß,
Peter
Moin,
irgendwie beschreibst du das alles ziemlich kompliziert - wohl auch weil du den Begriff "Datensatz" anders verwendest als ein Programmierer.
Aber es scheint mir so, also müsstest du einfach zwei oder mehr verschiedene Satzarten in eine Datenbank einlesen und jeweils einen vorhandenen Satz aktualisieren oder einen nicht vorhandenen einfügen. Das kann man natürlich machen, indem man Daten von einer CSV in die nächste schaufelt und nochmal von hinten durchs Knie...
Henning
irgendwie beschreibst du das alles ziemlich kompliziert - wohl auch weil du den Begriff "Datensatz" anders verwendest als ein Programmierer.
Aber es scheint mir so, also müsstest du einfach zwei oder mehr verschiedene Satzarten in eine Datenbank einlesen und jeweils einen vorhandenen Satz aktualisieren oder einen nicht vorhandenen einfügen. Das kann man natürlich machen, indem man Daten von einer CSV in die nächste schaufelt und nochmal von hinten durchs Knie...
Ist es eine Option die Datenmengen in eine Datenbank (SQL Express, MYSQL, MariaDB, ... (MS-Access)) zu packen und dort die Duplicate erst gar nicht
Eigentlich die einzige vernünftige Option.Henning
Hallo,
https://de.wikipedia.org/wiki/CSV_(Dateiformat)
Ein Datensatz ist eher immer nur eine einzige Zeile. Alles andere ist eine Sammlung von Datensätze. Siehe auch das Beiapiel wo genau 4 Datensätze deine Sammlung darstellen. 1.te Zeile als Kopfzeile bzw. Beschreibung der Spalten und deren Festlegung. Zeile 3 - 4 sind dann die 3 enthaltenen Datensätze. Bei dir erkennbar das deine CSV sicht nicht an diese Konvention hält, daher eine CSV mit spziellen Aufbau bzw. von und für Spezielle Anwendungen. Alleine schon das deine CSV Dateien Kommentare enthalten zeigt das hier ein eine eigene Zusammenstellung von Informationen gemacht wurde und als Endung eben CSV verwendet, wobei das Comma Seperated Value schon beibehalten wurde. Daher eher ein Selbstdefiniertes CSV für Anwendung XYZ. Damit kann aber beim Import umgegangen werden sofern alle (CSV) Dateien sich dran halten.
http://stackoverflow.com/questions/1961006/can-a-csv-file-have-a-commen ...
. Das selbst ist nicht das Problem, sondern in beiden Beispielen sind die Datensätze gleich bzw. im 2ten fehlt einfach das Feld Note2 und dessen Daten ganz. Leere Datenfelder in CSV werden eher mit ;;; dargestellt, dann wieß jeder das hier eben keine Daten existieren bzw. die Datenfelder dann eben Leer sind (somit greift der Standard welcher für dieses Feld vorgesehen ist).

SQL Server Express = Kostenlos
MySQL = Kostenloas
MariaDB = Kostenlos
MS Access = nur in manchen Office Produkten enthalten oder halt die Runtime nutzen und Programmieren mit Visial Studio....
https://www.microsoft.com/de-de/download/details.aspx?id=42299 oder auch eine 2012 Version oder eine 2008 oder oder oder
Das sammeln dieser Daten ist wohl nicht deine Projektarbeit, sondern eher das Auswerten dieser Daten. Eine Datenbank ist hier nur der Ort wo du deine ganzen Daten(sätze) speicherst um diese dann dann auszuwerten.
Gruß,
Peter
https://de.wikipedia.org/wiki/CSV_(Dateiformat)
Ein Datensatz ist eher immer nur eine einzige Zeile. Alles andere ist eine Sammlung von Datensätze. Siehe auch das Beiapiel wo genau 4 Datensätze deine Sammlung darstellen. 1.te Zeile als Kopfzeile bzw. Beschreibung der Spalten und deren Festlegung. Zeile 3 - 4 sind dann die 3 enthaltenen Datensätze. Bei dir erkennbar das deine CSV sicht nicht an diese Konvention hält, daher eine CSV mit spziellen Aufbau bzw. von und für Spezielle Anwendungen. Alleine schon das deine CSV Dateien Kommentare enthalten zeigt das hier ein eine eigene Zusammenstellung von Informationen gemacht wurde und als Endung eben CSV verwendet, wobei das Comma Seperated Value schon beibehalten wurde. Daher eher ein Selbstdefiniertes CSV für Anwendung XYZ. Damit kann aber beim Import umgegangen werden sofern alle (CSV) Dateien sich dran halten.
http://stackoverflow.com/questions/1961006/can-a-csv-file-have-a-commen ...
In einem Jahr sind die CSV Dateien in der Regel gleich aufgebaut. In einem bestimmten Jahr liegen jedoch durch hinzufügen einer weiteren Spalte zwei unterschiedliche CSV Dateien
Das ist kein Problem. Es sollte nur klar sein welche Daten wohin gehören. Deine Beispiel geht auch nicht auf. Einmal folgender Kopf# [Colour];[Car];[TimeStamp];[Note];[PublicationTimeStamp];[ModificationTimeStamp]</code und dann# [Colour];[Car];[TimeStamp];[Note];[Note2];[PublicationTimeStamp];[ModificationTimeStamp]
ab dem folgenden Jahr geht es mit dem neuen CSV Typ weiter
Immer der grösste gemeinsame Nenner, hier Spalten eines Datensatzes (Zeile in einer CSV Datei) nehmen.Innerhalb einer CSV Datei gibt es mehrer Zeilen mit unterschiedlichen aber auch teils doppelten Zeilen.
Kann ja per Duplikat entfernt werden wenn der datensatz Dupliziert ist. Es kommt darauf an was du mit den Daten anstellen willst. Nur sammeln wohl nicht Es ist gut möglich, dass es mit den Datenbanken besser funktioniert.
Als aufbewahrungsort deiner gesammelten Daten, Ja.Jedoch steht mir allerhöchstens eine Access Datenbank zur Verfügung.
OK, Nimm es.Bzw. falls es möglich ist eine offline SQL Datenbank
Was bitte ist eine Offline SQL Datenbank und wie willst die dann Benutzen? Eine Datenbank die irgendwo rumliegt aber keiner dran kommt?SQL Server Express = Kostenlos
MySQL = Kostenloas
MariaDB = Kostenlos
MS Access = nur in manchen Office Produkten enthalten oder halt die Runtime nutzen und Programmieren mit Visial Studio....
https://www.microsoft.com/de-de/download/details.aspx?id=42299 oder auch eine 2012 Version oder eine 2008 oder oder oder
Das sammeln dieser Daten ist wohl nicht deine Projektarbeit, sondern eher das Auswerten dieser Daten. Eine Datenbank ist hier nur der Ort wo du deine ganzen Daten(sätze) speicherst um diese dann dann auszuwerten.
Gruß,
Peter
Hallo,
Jetzt passts. Und von diesen CSV Dateien kommst du auf mehrere hundert Tausende. Und wie viele Datensätze sind es dann (grobe Schätzung reicht) - mehar als 5.000.000 oder was?

MySQL
MariaDB
...
Je nach womit du später da dran kommen tust bzw. willst.
Gruß,
Peter
Jetzt passts. Und von diesen CSV Dateien kommst du auf mehrere hundert Tausende. Und wie viele Datensätze sind es dann (grobe Schätzung reicht) - mehar als 5.000.000 oder was?
Nein wie gesagt ich möchte sie Auswerten.
haben wir schon Vermutet Teilweise wurden Daten aktualisiert und mit einem neuen ModificationTimestamp hinzugefügt. In die Datenbank soll dann nur der aktuellste wert übernommen werden.
Bleibt also Pro getrennten Datensatz nur einer übrig. Wie viele sind das dann (Geschätzt)?Zur Auswertung muss ich natürlich andere Programme nutzen.
Ist das schon gegeben oder kannst du da machen was du willst?Derzeit besteht jedoch mein Problem, dass ich noch keine geeignete Variante gefunden habe mit deratig großen Datenmengen klar zu kommen.
SQL Server (MS)MySQL
MariaDB
...
Je nach womit du später da dran kommen tust bzw. willst.
Sie müssen bereinigt werden, da sie anschließend viel einfacher und sogar mit Excel zu bändigen sind.
Excel kannt auch auf SQL Datenbanken zugreifen, oder MS Access,Ist der Weg über die Datenbank hier sinnvoller, als über eine Modifizierte version meines PowerShell Skripts ?
Zum zusammenstellen bzw. sammeln der Daten? Ja.Gemeint war eine aktive SQL Datenbank (online), die jedoch nicht vom Internet zugänglich ist. Sorry für die falsche Verwendung des Begriffes "online"
SQL Datenbank ist nicht zwingend Online, kann aber wenn es sein muss auch ins Internet gestellt werden. Wenn eine Datenbank Offline ist, ist dies eben nicht zugreifbar bzw. du kommst an keine Daten ran. Inter und SQL sind zwei völlig von einander losgelöste Begriffe. Ein SQL Datenbank per WAN zu nutzen ist eher wie die Daten mit Meißel und Schiefertafel zu nutzen. Macht kein sinn. Da gibt es dann Server/Dienste dazwischen...Genau, ich brauche jedoch auswertbare Daten und in der Form, wie sie mir derzeit vorliegen geht es nicht.
Der Transport deiner Daten wird per CSV gemacht. Zugreifen musst du allerdings auf die einzelen Datenzielen (Datensätze) und dor insbesonders auf die einzelnen Datenfelder, wobei ein Datensatz nicht auseinander gerissen werden darf (Seine Datenfelder nicht über verschiedene Zeilen verteilen darf).Gruß,
Peter