CSV Datei: Zahlen Genauigkeit reduzieren 3.00000001 -> 3.00E+0

Gast #4765960
Lesenswert?

Hallo,
ich habe CSV Dateien die eine große Dateigröße haben und deshalb schwer 
zu verarbeiten sind.

Die Daten sind im Format (beispielhaft)
1
X,Y,Z
2
1.00010001,  5.003, 1.000500001E-20
3
1.99999999, 10.001, 2.020100005E-21
4
3.02000001, 14.999, 3.000000011E-20
(Leerzeichen sind in der Datei nicht vorhanden, nur zur besseren 
Lesbarkeit)

Dh. die Zahlen haben einerseits sehr viele Nachkommastellen und sind zum 
Teil in E+XX Schreibweise.

Ich möchte jeztzt ein Skript schreiben, dass die Datei einliest, alle 
Zahlen auf eine vorgegebene Anzahl von Dezimalstellen rundet (bzw. 
abschneidet) und dann in eine neue Datei speichert.

Die Ausgabe sollte z.B. bei "3 Stellen Genaugigkeit" so aussehen:
1
X,Y,Z
2
1.00,  5.00,    1.00E-20
3
2.00,  1.00E+1, 2.00E-21
4
3.02,  1.50E+1, 3.00E-20
(ebenfalls Beispielhaft, ob alle Zahlen ein E+XX Format bekommen ist 
egal. Leerzeichen nur zur besseren Lesbarkeit eingefügt)

Danke schonmal
Moritz

PS: Skriptsprache ist egal, am liebsten etwas das unter Windows+Linux 
läuft (z.B. Python?)
#4766039
Lesenswert?

Dein Skript heißt LibreOffice.

Dort kann man Tabellen so als .csv exportieren, wie sie auf dem 
Bilschirm formatiert dargestellt sind.
Also einmal importieren, so formatieren, wie Du's haben willst und beim 
Wiederexportieren den Knopf "Zellinhalt wie angezeigt speichern" 
drücken.

Ob das in Excel auch geht, weiß ich nicht.
Gast #4766050
Lesenswert?

Danke schonmal für die Tipps.

Ich suche nach einer automatisierbaren Lösung, d.h. nicht Excel.

Im Idealfall kann ich das Skript per Kommandozeile starten, z.b.
1
convertSkript input.csv output.csv

Und es erstellt eine neue Datei mit reduzierter Genauigkeit der Daten.

Grüße
Moritz
Gast #4766053
Lesenswert?

Moritz schrieb:
> Ich suche nach einer automatisierbaren Lösung, d.h. nicht Excel.
>
> Im Idealfall kann ich das Skript per Kommandozeile starten, z.b.
> convertSkript input.csv output.csv
> Und es erstellt eine neue Datei mit reduzierter Genauigkeit der Daten.

Da musst DU wohl was tun ...
Gast #4766078
Lesenswert?

Foren wie diese sind eigentlich dafür gedacht, Leuten, die ein Problem 
mit irgendetwas haben, auf die Sprünge zu helfen oder Tipps zu geben. 
Das hier dient nicht dazu, für Lau Programme erstellt zu bekommen.
Gast #4766084
Lesenswert?

Hier eine Lösung mit Perl:
1
> cat csv
2
X,Y,Z
3
1.00010001,  5.003, 1.000500001E-20
4
1.99999999, 10.001, 2.020100005E-21
5
3.02000001, 14.999, 3.000000011E-20
6

7
> cat csv | perl -pe 's/([0-9]+\.[0-9]+([eE][ +-][0-9]+)?)/sprintf("%0.3g", $1)/ge'
8
X,Y,Z
9
1,  5, 1e-20
10
2, 10, 2.02e-21
11
3.02, 15, 3e-20
Gast #4766101
Lesenswert?

Hier eine Lösung in C# (sollte in jede Sprache übertragen werden können)
1
static void Main(string[] args)
2
        {
3
            Regex regex = new Regex((@"-?\d +.?\d *)(E[+-]\d +) ?"));
4
            var temp = File.ReadAllText(args[0]);
5
            regex.Matches(temp).Cast<Match>().Select(match => match.Value).ToList().ForEach(match => {
6
                temp.Replace(match, Math.Round(Convert.ToDouble(match), Convert.ToInt32(args[2])).ToString());
7
            });
8
            File.WriteAllText(args[1], temp);
9
        }

Kann somit über die Kommandozeile mit <input.csv> <output.csv> <Stelle 
auf die gerundet werden soll> aufgerufen werden.
#4766127
Lesenswert?

Ich Vergaß (doppelt)!

Vor kurzem habe ich einen Artikel gelesen, nachdem 30% (man höre und 
staune) aller in (vom allem von Microsoft) Tabellen vorhandenen Daten, 
grobe Fehler enthalten. Vor allem durch nachträgliche "Verbesserungen". 
Oft beim Versionssprung automatisch durchgeführt!

Wenn Du Dich persönlich hier einreihen möchtest: Hau rein!
Gast #4766344
Lesenswert?

Vielen Dank für die Hilfe, insbesondere mit dem regulären Ausdruck. 
Besten Dank.

PS: Ein Forum lebt vom geben und nehmen, deshalb freut es mich dass eine 
funktionsfähige Lösungen von Personen gepostet werden für die die 
Aufgabe leicht lösbar ist. Wenn die Person (ich) der damit Arbeit 
abgenommen wurde dann im Umkehrschluss in anderen Threads ebenfalls 
selbstlos Hilfe anbietet und anderen Zeit erspart haben alle profitiert. 
Insofern kann ich die Nörgler nicht verstehen und mich umsomehr bei den 
aktiven des Forums bedanken!

Grüße

Hilfreiche Person schrieb:
> Hier eine Lösung mit Perl:> cat csv
> X,Y,Z
> 1.00010001,  5.003, 1.000500001E-20
> 1.99999999, 10.001, 2.020100005E-21
> 3.02000001, 14.999, 3.000000011E-20
>
>> cat csv | perl -pe 's/([0-9]+\.[0-9]+([eE][ +-][0-9]+)?)/sprintf("%0.3g",
> $1)/ge'
> X,Y,Z
> 1,  5, 1e-20
> 2, 10, 2.02e-21
> 3.02, 15, 3e-20

Vielleicht hilfreich schrieb:
> Hier eine Lösung in C# (sollte in jede Sprache übertragen werden können)
> static void Main(string[] args)
>         {
>             Regex regex = new Regex((@"-?\d +.?\d *)(E[+-]\d +) ?"));
>             var temp = File.ReadAllText(args[0]);
>             regex.Matches(temp).Cast<Match>().Select(match =>
> match.Value).ToList().ForEach(match => {
>                 temp.Replace(match, Math.Round(Convert.ToDouble(match),
> Convert.ToInt32(args[2])).ToString());
>             });
>             File.WriteAllText(args[1], temp);
>         }
>
> Kann somit über die Kommandozeile mit <input.csv> <output.csv> <Stelle
> auf die gerundet werden soll> aufgerufen werden.
#4767120
Lesenswert?

Moritz schrieb:
> ich habe CSV Dateien die eine große Dateigröße haben und deshalb schwer
> zu verarbeiten sind.

Ganz sicher? CSV wird normalerweise mit Interface-geschwindigkeit 
eingelesen.
D.h. Du würdest die Änderungen nur auf einem ganz lahmen NAS oder 
uraltem USB Stick merken, und das auch nur bei Dateien in GB Größe.

Ich sehe da überhaupt kein Einsparpotential: Die Konvertierung dauert 
viel länger als Du durch das ein ganz kleines bißchen schnellere 
Einlesen sparen wirst.

Drei signifikate Stellen sind übrigens nur ca. 10 Bit, gute ADCs gibt es 
mit 12, 14,..,24 Bit je nach Anwendung. Falls die Daten also nicht aus 
einem Arduino rausfallen wirfst Du hier Auflösung weg.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren