Nodes/ComfyDL/Dataset → Write CSV
ComfyUI Node

Dataset → Write CSV

The end of the chain, and the label column's name is not what you think

By Cynthia-lxx·Created 3 months ago·Updated 12 days ago· 7
Dataset → Write CSV
  • dataset
  • file
◄filedataset_out.csv►
◄indexfalse►

What it is

ComfyDL is Cynthia-lxx's d2l-derived pack for doing actual training inside ComfyUI as a graph, and its data side speaks one universal DATASET type: features, optional labels, column names, passed by reference. The writers are where that data leaves the graph again.

Dataset → Write CSV dumps a DATASET to a .csv and - the useful part - hands the path back out as a STRING. That makes it chainable: convert a database query to a file, cache a cleaned dataset, or hand a result to something that isn't ComfyUI.

You could argue a save node is a save node. The reason this one is worth knowing is the chaining, and one naming detail that surprises everybody the first time.

How it works

It materialises the dataset with dataset.to_dataframe() - a copy built from the stored feature tensor plus column names - then calls df.to_csv(file, index=index) with whatever index you set. The header row comes from feature_names.

The label column's name comes from the dataset's target_name, falling back to the literal string label:

df[self.target_name or "label"] = self.labels.reshape(-1).numpy()

So a dataset read from a CSV with target = "price" writes back a price column. A dataset you assembled with Tensors → Dataset has no target name and writes out a column called label. Round-tripping through the pack's own JSON writer and reader preserves this; building the dataset from bare tensors doesn't, because there was never a name to preserve.

Inputs and outputs

Required: dataset (a forced input socket - wire one in) and file (STRING, default dataset_out.csv). Optional: index (default False - leave it, unless you actually want pandas' row numbers as a column).

Output: file, a STRING holding the path you just wrote. That's what you wire onward.

Install

Manager → search ComfyDL, or:

cd ComfyUI/custom_nodes
git clone https://github.com/Cynthia-lxx/ComfyDL
pip install -r ./ComfyDL/requirements.txt

Restart. The declared requirements are only matplotlib, IPython and matplotlib-inline - pandas does the actual writing and is assumed to be in your ComfyUI environment already. And keep this in the back of your mind: the pack imports node modules inside a try/except that prints [ComfyDL] Warning: Failed to load <module> to the console, so a broken dependency shows up as a missing node, not an error dialog.

Chaining it, which is the point

The file output exists so you can wire it into another node's path field. To do that, right-click the receiving node's file widget and convert it to an input socket, then connect. A tidy conversion graph looks like:

Read XLSX → Dataset  →  Dataset → Write CSV  ── file ──►  Read CSV → Dataset
                                                        →  Dataset → Preview

That's a workbook-to-CSV converter you can keep on the canvas. Defaults don't line up, by the way - the writer writes dataset_out.csv and the reader looks for cdl_dataset.csv - so if you're not wiring the path through, set both fields deliberately. Absolute paths for both; relative ones resolve against ComfyUI's working directory.

Where people get burned

Unlabelled datasets write without a label column. That's correct behaviour and easy to misread as data loss. If your target was empty, or the reader never matched it, the CSV has features only.

Column names from tensors are generic. x0, x1, x2, label. If you care about headers, go back to the reader.

The file is overwritten without asking. Same name, same folder, gone - to_csv truncates. Use a distinct filename per run.

Full path required in practice. dataset_out.csv lands in ComfyUI's process working directory, which is rarely where you're looking. Absolute paths make this a non-issue.

Nothing renames or dedupes. Whatever's in the dataset gets written, NaNs included, so a downstream reader hands you the same NaN problem back.

Big datasets are copied twice - once into the DataFrame, once into the file - so peak RAM is roughly the dataset plus its CSV text. For very large tables the DB writer is the more considerate choice, since it streams in chunks.

Categoryd2l/Datasets

Inputs (3)

NameTypeDefaultDescription
datasetDATASET—
fileSTRINGdataset_out.csv—
indexoptBOOLEANfalse—

Outputs (1)

NameTypeDescription
fileSTRING—