#[derive(DataFrameRow)]
{
// Attributes available to this derive:
#[dataframe]
}
Expand description
Derive DataFrameRow: generates a companion *DataFrame type with collection fields,
plus IntoR / TryFromSexp / IntoDataFrame impls for seamless R data.frame conversion.
§Example
#[derive(DataFrameRow)]
struct Measurement {
time: f64,
value: f64,
}
// Generates MeasurementDataFrame { time: Vec<f64>, value: Vec<f64> }
// plus conversion impls§Struct-level attributes
#[dataframe(name = "CustomDf")]— custom name for the generated DataFrame type#[dataframe(align)]— pad shorter columns with NA to match longest#[dataframe(tag = "my_tag")]— attach a tag attribute to the data.frame#[dataframe(conflicts = "string")]— resolve conflicting column types as strings
§Field-level attributes
#[dataframe(skip)]— omit this field from the DataFrame#[dataframe(rename = "col")]— custom column name#[dataframe(as_list)]— keep collection as single list column (no expansion)#[dataframe(expand)]/#[dataframe(unnest)]— expand collection into suffixed columns#[dataframe(width = N)]— pin expansion width (shorter rows get NA)
§Requirements
Of each field type the derive asks only what turning that field into columns needs, and a missing impl is reported at the field:
- a scalar or opaque column: its column converts to R (
Vec<T>: IntoR; in an enum,Vec<Option<T>>); [T; N], orwidth/expandover an ownedVec<T>/Box<[T]>:T’s columns convert to R; the elements are moved, soTneeds noCloneorCopy. Over a borrowed&[T; N]/&[T],Tmust also beClone;- a flattened struct or nested enum:
#[derive(DataFrameRow)]; as_factor:UnitEnumFactor, which#[derive(DataFrameRow)]on a unit-only enum and#[derive(RFactor)]both provide;as_list:IntoList;skip: nothing.
Everything else is generated only where the field types allow it. The
companion is Debug / Clone when every column type is. A struct
companion iterates its rows when every skip field’s type is Default
(they are rebuilt with Default::default()). With rayon,
from_rows_par fills the columns in parallel when the rows and column
values are Send, placeholder-filled struct columns are Default, and
flattened / as_list values are Clone; otherwise it fills them
sequentially.
§Public surface (which verbs to call)
Every capability the derive provides has a documented, trait-based (or std)
verb — reach for these, not any incidental inherent plumbing:
- Rows → R
data.frame:rows.into_dataframe()?(owned, GC-rootedBuiltDataFrame) orrows.wrap_data_frame()(deferredIntoRwrapper); parallel variantrows.into_dataframe_par()?. From theIntoDataFrame/AsDataFrameExttraits (both re-exported fromminiextendr_api::prelude). - R
data.frame→ rows:Vec::<Row>::from_dataframe(&df)?(parallel:Vec::<Row>::from_dataframe_par(&df)?), from theFromDataFrametrait — or the one-callRow::try_from_dataframe(sexp)reader on the row type. - Rows ↔ the pure-Rust columnar companion (
<Row>DataFrame,Vec-columns, no R involved): theColumnarFrametrait (in the prelude) —<Row>DataFrame::from_rows(rows)/from_rows_par(rows)(parallel build of the companion, whichinto_dataframe_pardoes not give you) and, for row-iterable companions,companion.into_rows().Vec<Row>: Into<companion>and the companion’sIntoIteratorare the equivalentstdverbs. - Enum split representation:
rows.into_dataframe_split()returns onedata.frameper variant (only that variant’s columns — no NA fill) as a GC-rootedDataFrameShape—Barefor a single-variant enum,PerVariantList(an R named list) otherwise — from theIntoDataFrameSplittrait (in the prelude). Enum rows only; struct derives don’t partition.
The generated <Row>DataFrame / <Row>DataFrameIter types are intermediate
column-oriented companions; you rarely name them directly.