data/ — Lyx Data Library
Pandas-ähnliche Datenanalyse-Bibliothek für Lyx. Die data/-Units sind eigenständig vom std/-Namespace und werden separat importiert. Sie richten sich an Datenanalyse, ETL-Pipelines, maschinelles Lernen und statistische Auswertungen — mit native Lyx-Implementierungen ohne externe Abhängigkeiten.
| Unit | Quelldatei | Beschreibung |
data.core | data/core.lyx | Kern-Datenstrukturen: Series, DataFrame, Statistik, GroupBy, Joins |
data.io | data/io.lyx | CSV-Import und -Export |
data.stats_batch | data/stats_batch.lyx | SIMD-bereite Batch-Statistikfunktionen |
data.core
Konstanten
Spaltentypen
| Konstante | Wert | Beschreibung |
COL_INT64 | 1 | Ganzzahl (int64) |
COL_FLOAT | 2 | Fließkomma (f64) |
COL_STRING | 3 | Zeichenkette (pchar) |
COL_BOOL | 4 | Boolean |
Vergleichsoperatoren (für DataFrameFilter / CompareInt)
| Konstante | Operator |
OP_EQ | == |
OP_NE | != |
OP_LT | < |
OP_LE | ⇐ |
OP_GT | > |
OP_GE | >= |
Join-Typen
| Konstante | Bedeutung |
JOIN_INNER | Inner Join |
JOIN_LEFT | Left Join |
JOIN_RIGHT | Right Join |
JOIN_OUTER | Outer Join |
Aggregationstypen (für SeriesAgg / DataFrameAgg)
| Konstante | Bedeutung |
AGG_SUM | Summe |
AGG_MEAN | Mittelwert |
AGG_MIN | Minimum |
AGG_MAX | Maximum |
AGG_COUNT | Anzahl Nicht-Null-Werte |
AGG_STD | Standardabweichung |
Typen
Series
Eindimensionales typisiertes Array mit optionalen Labels.
type Series = struct {
data: int64; // Pointer auf Datenspeicher (int64*)
labels: int64; // Pointer auf Labelarray (pchar*), 0 = kein Label
length: int64; // Anzahl Elemente
colType: int64; // COL_INT64 | COL_FLOAT | COL_STRING | COL_BOOL
name: int64; // Spaltenname (pchar)
};
DataFrame
Zweidimensionale Tabelle mit benannten Spalten.
type DataFrame = struct {
columns: int64; // Pointer auf Column-Array (je 16 Byte)
colCount: int64;
rowCount: int64;
colCapacity: int64; // max. 16 Spalten
rowCapacity: int64; // max. 1024 Zeilen
index: int64; // Pointer auf Index-Labels (pchar*), 0 = kein Index
indexName: int64; // Indexname (pchar)
hasIndex: int64; // 1 wenn Index gesetzt
};
DateTime
Aufgeschlüsselte Unix-Zeitangabe.
type DateTime = struct {
year: int64; month: int64; day: int64;
hour: int64; minute: int64; second: int64;
};
BoolSeries
Ergebnis eines booleschen Vergleichs auf einer Series.
type BoolSeries = struct {
data: int64; // Pointer auf bool-Array (0/1 als int64)
length: int64;
name: int64;
};
AggResult
Mehrfach-Aggregationsergebnis für SeriesAggMulti.
type AggResult = struct {
sum: int64; mean: int64; min: int64; max: int64; count: int64;
};
GroupByResult
Ergebnis von DataFrameGroupBy.
type GroupByResult = struct {
df: DataFrame;
keyCol: int64; // Pointer auf Schlüsselspaltenname
groups: int64; // Pointer auf unique Schlüsselwerte
groupRows: int64; // Pointer auf Zeilenindizes je Gruppe
groupCount: int64;
};
MultiGroupByResult
Ergebnis von DataFrameGroupByMulti (mehrere Schlüsselspalten).
type MultiGroupByResult = struct {
df: DataFrame;
keyCols: int64; // Pointer auf Array von Spaltennamen-Pointern
keyColCount: int64;
groups: int64;
groupRows: int64;
groupCount: int64;
};
Funktionen
Series erstellen
| Funktion | Signatur | Beschreibung |
SeriesNewInt64 | (name, capacity: int64): Series | Neue int64-Series |
SeriesNewString | (name, capacity: int64): Series | Neue String-Series |
SeriesNewFloat64 | (name, capacity: int64): Series | Neue float64-Series |
Series lesen/schreiben
| Funktion | Signatur | Beschreibung |
SeriesGetInt | (s: Series, idx: int64): int64 | Ganzzahlwert bei Index |
SeriesSetInt | (s: Series, idx, value: int64) | Ganzzahlwert setzen |
SeriesGetString | (s: Series, idx: int64): int64 | String-Pointer bei Index |
SeriesSetString | (s: Series, idx, value: int64) | String-Pointer setzen |
SeriesGetLabel | (s: Series, idx: int64): int64 | Label bei Index |
SeriesSetLabel | (s: Series, idx, label: int64) | Label setzen |
SeriesGetLabelString | (s: Series, idx: int64): int64 | String-Label bei Index |
SeriesAppendInt | (s: Series, value: int64) | Wert anhängen |
SeriesAppendString | (s: Series, value: int64) | String-Pointer anhängen |
DataFrame erstellen und befüllen
| Funktion | Signatur | Beschreibung |
DataFrameNew | (): DataFrame | Leeren DataFrame erstellen |
DataFrameAddColumn | (df: DataFrame, name: int64, colType: int64) | Spalte hinzufügen |
DataFrameAddColumnFloat64 | (df: DataFrame, name: int64) | float64-Spalte hinzufügen |
DataFrameAppendRow | (df: DataFrame) | Zeile anhängen (alle Spalten auf 0/NULL) |
DataFrame lesen/schreiben
| Funktion | Signatur | Beschreibung |
DataFrameGetInt | (df: DataFrame, colName: int64, row: int64): int64 | int64-Wert lesen |
DataFrameSetInt | (df: DataFrame, colName: int64, row, value: int64) | int64-Wert setzen |
DataFrameGetString | (df: DataFrame, colName: int64, row: int64): int64 | String-Pointer lesen |
DataFrameSetString | (df: DataFrame, colName: int64, row, value: int64) | String-Pointer setzen |
DataFrameGetFloat64 | (df: DataFrame, colName: int64, row: int64): f64 | f64-Wert lesen |
DataFrameSetFloat64 | (df: DataFrame, colName: int64, row: int64, value: f64) | f64-Wert setzen |
DataFrameGetFloat | (df: DataFrame, colName: int64, row: int64): int64 | Float als Bitpattern lesen |
DataFrameSetFloat | (df: DataFrame, colName: int64, row, value: int64) | Float als Bitpattern setzen |
DataFrameGetColumnType | (df: DataFrame, colName: int64): int64 | Spaltentyp abfragen |
Spalten und Index verwalten
| Funktion | Signatur | Beschreibung |
DataFrameColIndex | (df: DataFrame, name: int64): int64 | Spalten-Index by Name (-1 wenn nicht gefunden) |
DataFrameGetSeries | (df: DataFrame, name: int64): Series | Series by Spaltenname |
DataFrameDropColumn | (df: DataFrame, name: int64) | Spalte löschen |
DataFrameRenameColumn | (df: DataFrame, oldName, newName: int64) | Spalte umbenennen |
DataFrameSetIndex | (df: DataFrame, labels, name: int64) | Index manuell setzen |
DataFrameSetIndexFromColumn | (df: DataFrame, colName: int64) | Spalte als Index verwenden |
DataFrameSetMultiIndex | (df: DataFrame, col1, col2: int64) | Zwei Spalten als kombinierten Index |
DataFrameResetIndex | (df: DataFrame) | Index auf numerisch zurücksetzen |
DataFrameGetIndexLabel | (df: DataFrame, row: int64): int64 | Index-Label bei Zeile |
DataFrameSetIndexLabel | (df: DataFrame, row, label: int64) | Index-Label setzen |
DataFrameGetIndexName | (df: DataFrame): int64 | Indexname |
DataFrameHasIndex | (df: DataFrame): int64 | 1 wenn Index vorhanden |
DataFrameIndexLookup | (df: DataFrame, label: int64): int64 | Zeilennummer per Index-Label suchen |
DataFrameGetIntByLabel | (df: DataFrame, colName, label: int64): int64 | Wert per Index-Label lesen |
DataFrameSetIntByLabel | (df: DataFrame, colName, label, value: int64) | Wert per Index-Label setzen |
Filtern, Selektieren, Slicen
| Funktion | Signatur | Beschreibung |
DataFrameFilter | (df: DataFrame, colName: int64, op, value: int64): DataFrame | Zeilen nach Spaltenvergleich filtern |
DataFrameQuery | (df: DataFrame, colName: int64, op, value: int64): DataFrame | Alias für DataFrameFilter |
DataFrameFilterByMask | (df: DataFrame, mask: BoolSeries): DataFrame | Zeilen per BoolSeries filtern |
DataFrameSlice | (df: DataFrame, start, endRow: int64): DataFrame | Zeilenbereich [start, end) |
DataFrameHead | (df: DataFrame, n: int64): DataFrame | Erste N Zeilen |
DataFrameTail | (df: DataFrame, n: int64): DataFrame | Letzte N Zeilen |
DataFrameSample | (df: DataFrame, fraction: int64): DataFrame | Jede N-te Zeile (fraction in %) |
CompareInt | (value, op, target: int64): int64 | Einzelwert vergleichen (1 = wahr) |
Sortieren
| Funktion | Signatur | Beschreibung |
DataFrameSortBy | (df: DataFrame, colName: int64): DataFrame | Aufsteigend sortieren |
DataFrameSortByDesc | (df: DataFrame, colName: int64): DataFrame | Absteigend sortieren |
DataFrameReverse | (df: DataFrame): DataFrame | Zeilenreihenfolge umkehren |
| Funktion | Signatur | Beschreibung |
DataFrameConcat | (left, right: DataFrame): DataFrame | Zeilen anhängen (gleiche Spalten) |
DataFrameJoinInner | (left: DataFrame, leftKey: int64, right: DataFrame, rightKey: int64): DataFrame | Inner Join |
DataFrameJoinLeft | (left: DataFrame, leftKey: int64, right: DataFrame, rightKey: int64): DataFrame | Left Join |
DataFrameJoinRight | (left: DataFrame, leftKey: int64, right: DataFrame, rightKey: int64): DataFrame | Right Join |
DataFrameJoinOuter | (left: DataFrame, leftKey: int64, right: DataFrame, rightKey: int64): DataFrame | Outer Join |
DataFramePivot | (df: DataFrame, indexCol, pivotCol, valueCol: int64): DataFrame | Long → Wide |
DataFrameMelt | (df: DataFrame, idCol: int64, valueColStart, valueColEnd: int64): DataFrame | Wide → Long |
DataFrameExplode | (df: DataFrame, colName: int64): DataFrame | Zeilen expandieren |
DataFrameGetDummies | (df: DataFrame, colName: int64): DataFrame | One-Hot-Encoding einer Spalte |
Werte ersetzen und bereinigen
| Funktion | Signatur | Beschreibung |
DataFrameReplace | (df: DataFrame, colName: int64, oldVal, newVal: int64) | Wert in einer Spalte ersetzen |
DataFrameReplaceAll | (df: DataFrame, oldVal, newVal: int64) | Wert in allen Spalten ersetzen |
DataFrameMapMul | (df: DataFrame, colName: int64, factor: int64) | Spalte mit Faktor multiplizieren |
DataFrameMapAdd | (df: DataFrame, colName: int64, offset: int64) | Konstante zur Spalte addieren |
DataFrameClip | (df: DataFrame, colName: int64, minValue, maxValue: int64) | Werte auf [min, max] begrenzen |
DataFrameFillNA | (df: DataFrame, colName: int64, defaultValue: int64) | Nullwerte auffüllen |
DataFrameDropNA | (df: DataFrame, colName: int64): DataFrame | Zeilen mit Nullwert entfernen |
DataFrameDropDuplicates | (df: DataFrame, colName: int64): DataFrame | Doppelte Zeilen entfernen |
IsNA | (value, colType: int64): bool | Prüfen ob Wert NA (= 0) ist |
Statistik auf Series (int64)
| Funktion | Signatur | Beschreibung |
SeriesSum | (s: Series): int64 | Summe |
SeriesMean | (s: Series): int64 | Mittelwert |
SeriesMin | (s: Series): int64 | Minimum |
SeriesMax | (s: Series): int64 | Maximum |
SeriesCount | (s: Series): int64 | Anzahl Nicht-Null-Werte |
SeriesMedian | (s: Series): int64 | Median (intern sortiert) |
SeriesCorr | (s1, s2: Series): int64 | Pearson-Korrelation × 1000 |
SeriesCov | (s1, s2: Series): int64 | Kovarianz |
SeriesDescribe | (s: Series): DataFrame | Zusammenfassung: count, mean, std, min, max |
SeriesValueCounts | (s: Series): DataFrame | Häufigkeitstabelle (Spalten: value, count) |
SeriesAgg | (s: Series, aggType: int64): int64 | Einzelne Aggregation (AGG_*) |
SeriesAggMulti | (s: Series): AggResult | Alle Aggregationen auf einmal |
SeriesRank | (s: Series): Series | Aufsteigender Rang je Element |
SeriesIsDuplicated | (s: Series, idx: int64): int64 | 1 wenn Wert vorher schon vorkam |
Statistik auf Series (f64)
| Funktion | Signatur | Beschreibung |
SeriesSumF64 | (s: Series): f64 | Summe |
SeriesMeanF64 | (s: Series): f64 | Mittelwert |
SeriesMinF64 | (s: Series): f64 | Minimum |
SeriesMaxF64 | (s: Series): f64 | Maximum |
SeriesVarianceF64 | (s: Series): f64 | Varianz |
SeriesStdDevF64 | (s: Series): f64 | Standardabweichung (Newton) |
SeriesSumFloat | (s: Series): int64 | Summe als int64-Bitmuster |
SeriesMeanFloat | (s: Series): int64 | Mittelwert als int64-Bitmuster |
DataFrame-Aggregation
| Funktion | Signatur | Beschreibung |
DataFrameAgg | (df: DataFrame, aggType: int64): DataFrame | Aggregation aller Spalten |
DataFrameCorrMatrix | (df: DataFrame): DataFrame | Korrelationsmatrix aller Spalten |
Rolling Window (int64)
| Funktion | Signatur | Beschreibung |
SeriesRollingMean | (s: Series, window: int64): Series | Gleitender Mittelwert |
SeriesRollingSum | (s: Series, window: int64): Series | Gleitende Summe |
SeriesRollingMin | (s: Series, window: int64): Series | Gleitendes Minimum |
SeriesRollingMax | (s: Series, window: int64): Series | Gleitendes Maximum |
Kumulierte Werte
| Funktion | Signatur | Beschreibung |
SeriesCumSum | (s: Series): Series | Kumulative Summe (int64) |
SeriesCumSumF64 | (s: Series): Series | Kumulative Summe (f64) |
SeriesCumProd | (s: Series): Series | Kumulatives Produkt |
SeriesCumMax | (s: Series): Series | Kumulatives Maximum |
SeriesCumMin | (s: Series): Series | Kumulatives Minimum |
Verschieben und Differenz
| Funktion | Signatur | Beschreibung |
SeriesShift | (s: Series, n: int64): Series | Werte um N Positionen verschieben |
SeriesDiff | (s: Series): Series | Differenz aufeinanderfolgender Elemente |
Normalisierung
| Funktion | Signatur | Beschreibung |
SeriesNormalizeMinMax | (s: Series): Series | Min-Max auf Skala 0–1000 |
SeriesNormalizeZScore | (s: Series): Series | Z-Score (×100, integer) |
| Funktion | Signatur | Beschreibung |
SeriesTransformMul | (s: Series, factor: int64): Series | Alle Werte multiplizieren |
SeriesTransformAdd | (s: Series, offset: int64): Series | Konstante addieren |
SeriesTransformNormalize | (s: Series): Series | Min-Max-Normalisierung |
SeriesApplyAbs | (s: Series): Series | Absolutwert |
SeriesApplySquare | (s: Series): Series | Quadrat |
SeriesApplySqrt | (s: Series): Series | Integer-Wurzel |
DataFrameApplyAdd | (df: DataFrame, colName: int64, offset: int64): Series | Spalte + Konstante |
DataFrameApplyMul | (df: DataFrame, colName: int64, factor: int64): Series | Spalte × Faktor |
DataFrameApplyNormalize | (df: DataFrame, colName: int64): Series | Spalte normalisieren |
Binning
| Funktion | Signatur | Beschreibung |
SeriesCut | (s: Series, bins: int64): Series | Gleichmäßige Bins |
SeriesQCut | (s: Series, quantiles: int64): Series | Quantil-basierte Bins |
Resampling / Interpolation
| Funktion | Signatur | Beschreibung |
SeriesResampleCount | (s: Series, windowSec: int64): Series | Häufigkeiten in Zeitfenstern |
SeriesInterpolate | (s: Series): Series | Lineare Interpolation fehlender Werte |
Filter auf f64
| Funktion | Signatur | Beschreibung |
SeriesFilterGtF64 | (s: Series, threshold: f64): Series | Werte > threshold |
SeriesFilterLtF64 | (s: Series, threshold: f64): Series | Werte < threshold |
Boolesche Indizierung
| Funktion | Signatur | Beschreibung |
SeriesGreaterThan | (s: Series, value: int64): BoolSeries | s > value |
SeriesLessThan | (s: Series, value: int64): BoolSeries | s < value |
SeriesEqual | (s: Series, value: int64): BoolSeries | s == value |
SeriesNotEqual | (s: Series, value: int64): BoolSeries | s != value |
SeriesInRange | (s: Series, min, max: int64): BoolSeries | min ≤ s ≤ max |
BoolSeriesAnd | (bs1, bs2: BoolSeries): BoolSeries | Logisches AND |
BoolSeriesOr | (bs1, bs2: BoolSeries): BoolSeries | Logisches OR |
BoolSeriesNot | (bs: BoolSeries): BoolSeries | Logisches NOT |
BoolSeriesCount | (bs: BoolSeries): int64 | Anzahl true-Einträge |
BoolSeriesAny | (bs: BoolSeries): int64 | 1 wenn mindestens ein true |
BoolSeriesAll | (bs: BoolSeries): int64 | 1 wenn alle true |
GroupBy
| Funktion | Signatur | Beschreibung |
DataFrameGroupBy | (df: DataFrame, keyCol: int64): GroupByResult | Gruppieren nach einer Spalte |
GroupBySum | (gb: GroupByResult, aggCol: int64): DataFrame | Summe je Gruppe |
GroupByCount | (gb: GroupByResult): DataFrame | Zeilenanzahl je Gruppe |
GroupByAgg | (gb: GroupByResult, aggCol: int64): DataFrame | count, sum, mean, min, max je Gruppe |
DataFrameGroupByMulti | (df: DataFrame, keyCols: int64, keyColCount: int64): MultiGroupByResult | Gruppieren nach mehreren Spalten |
GroupByMultiCount | (gb: MultiGroupByResult): DataFrame | Zeilenanzahl je Mehrfach-Gruppe |
Datum und Uhrzeit
| Funktion | Signatur | Beschreibung |
UnixToDateTime | (unix: int64): DateTime | Unix-Timestamp → DateTime-Struct |
UnixGetYear | (ts: int64): int64 | Jahr |
UnixGetMonth | (ts: int64): int64 | Monat |
UnixGetDay | (ts: int64): int64 | Tag |
UnixGetHour | (ts: int64): int64 | Stunde |
String-Hilfsfunktionen
| Funktion | Signatur | Beschreibung |
StrToUpper | (s: int64): int64 | Großbuchstaben (neues pchar) |
StrToLower | (s: int64): int64 | Kleinbuchstaben (neues pchar) |
StrTrimLeft | (s: int64): int64 | Führende Leerzeichen entfernen |
StrTrimRight | (s: int64): int64 | Nachfolgende Leerzeichen entfernen |
StrTrim | (s: int64): int64 | Beide Seiten trimmen |
StrSplit | (s, delim: int64): int64 | String splitten → Array von pchar |
StrJoin | (parts, count, delim: int64): int64 | Array von pchar → String |
StrContains | (s, needle: int64): int64 | Teilstring suchen (1 = gefunden) |
StrReplace | (s, old, newStr: int64): int64 | Erstes Vorkommen ersetzen |
Ausgabe
| Funktion | Signatur | Beschreibung |
DataFramePrint | (df: DataFrame) | Tabellenausgabe auf stdout |
DataFrameShape | (df: DataFrame) | (rows, cols) auf stdout |
DataFrameInfo | (df: DataFrame) | Spaltenübersicht mit Typen auf stdout |
data.io
import data.io;
Abhängigkeit: data.core
data.io liest CSV-Dateien in einen DataFrame ein und schreibt DataFrames als CSV zurück. Der Parser erkennt die erste Zeile als Header und interpretiert alle Zellwerte als int64. String-Spaltenwerte werden beim Lesen nicht als solche erkannt — für gemischte Daten müssen Spaltentypen nach dem Import manuell gesetzt werden.
Funktionen
| Funktion | Signatur | Beschreibung |
ReadCSV | (path: int64): DataFrame | CSV-Datei einlesen (max. 1 MB, 64 Spalten). Erste Zeile ist Header. |
WriteCSV | (df: DataFrame, path: int64): int64 | DataFrame in CSV schreiben. Gibt 0 bei Erfolg, -1 bei Fehler. |
Hinweise:
Beispiel
import data.core;
import data.io;
var df: DataFrame := ReadCSV("input.csv");
DataFrameMapMul(df, "price", 2);
WriteCSV(df, "output.csv");
data.stats_batch
import data.stats_batch;
SIMD-bereite Batch-Funktionen für direkt übergebene Werte — kein Series-Zugriff nötig. Ideal für kleine, feste Datenmengen (4, 8 oder 16 Werte), die in einer einzigen Operation ausgewertet werden sollen, ohne vorher eine Series aufzubauen.
Summe
| Funktion | Signatur | Beschreibung |
Sum4 | (v0, v1, v2, v3: int64): int64 | Summe von 4 Werten |
Sum8 | (v0..v7: int64): int64 | Summe von 8 Werten |
Sum16 | (v0..v15: int64): int64 | Summe von 16 Werten |
Minimum
| Funktion | Signatur | Beschreibung |
Min4 | (v0, v1, v2, v3: int64): int64 | Minimum von 4 Werten |
Min8 | (v0..v7: int64): int64 | Minimum von 8 Werten |
Maximum
| Funktion | Signatur | Beschreibung |
Max4 | (v0, v1, v2, v3: int64): int64 | Maximum von 4 Werten |
Max8 | (v0..v7: int64): int64 | Maximum von 8 Werten |
Durchschnitt
| Funktion | Signatur | Beschreibung |
Avg4 | (v0, v1, v2, v3: int64): int64 | Mittelwert von 4 Werten |
Avg8 | (v0..v7: int64): int64 | Mittelwert von 8 Werten |
Varianz und Standardabweichung
| Funktion | Signatur | Beschreibung |
Variance4 | (v0, v1, v2, v3: int64): int64 | Varianz von 4 Werten |
StdDev4 | (v0, v1, v2, v3: int64): int64 | Standardabweichung von 4 Werten (Newton-Sqrt) |
Spannweite
| Funktion | Signatur | Beschreibung |
Range4 | (v0, v1, v2, v3: int64): int64 | Max − Min von 4 Werten |
Vollständiges Beispiel
import data.core;
import data.io;
// DataFrame aufbauen
var df: DataFrame := DataFrameNew();
DataFrameAddColumn(df, "name", COL_STRING);
DataFrameAddColumn(df, "age", COL_INT64);
DataFrameAddColumn(df, "score", COL_INT64);
DataFrameAppendRow(df);
DataFrameSetString(df, "name", 0, "Alice");
DataFrameSetInt(df, "age", 0, 30);
DataFrameSetInt(df, "score", 0, 85);
DataFrameAppendRow(df);
DataFrameSetString(df, "name", 1, "Bob");
DataFrameSetInt(df, "age", 1, 25);
DataFrameSetInt(df, "score", 1, 92);
DataFrameAppendRow(df);
DataFrameSetString(df, "name", 2, "Carol");
DataFrameSetInt(df, "age", 2, 35);
DataFrameSetInt(df, "score", 2, 78);
// Filtern: score > 80
var filtered: DataFrame := DataFrameFilter(df, "score", OP_GT, 80);
DataFramePrint(filtered);
// Sortieren nach age
var sorted: DataFrame := DataFrameSortBy(df, "age");
DataFramePrint(sorted);
// Statistik
var scoreS: Series := DataFrameGetSeries(df, "score");
PrintInt(SeriesMean(scoreS)); // 85
PrintInt(SeriesMin(scoreS)); // 78
PrintInt(SeriesMax(scoreS)); // 92
// CSV speichern
WriteCSV(df, "output.csv");