DataFrame 1.0 Help

unfold

Returns a DataFrame in which the selected columns of objects are turned into ColumnGroups, with a column for every public property of these objects.

Related operations: Update / convert values

unfold(roots, maxDepth) { columns }: DataFrame unfold(columnNames): DataFrame

unfold builds the new columns the way toDataFrame() builds a DataFrame from a list of objects, but for a column inside an existing dataframe. It is useful when a column holds instances of ordinary classes — for example, the ones a library API returns — and you want to work with their properties as columns: select, filter, sort, or group by them.

See column selectors for how to select the columns for this operation.

Every example on this page uses the same classes and objects as the toDataFrame() example, in a column called student:

data class Name(val firstName: String, val lastName: String) data class Score(val subject: String, val value: Int) data class Student(val name: Name, val age: Int, val scores: List<Score>) val df = dataFrameOf( "id" to columnOf(1, 2), "student" to columnOf( Student(Name("Alice", "Cooper"), 15, listOf(Score("math", 4), Score("biology", 3))), Student(Name("Bob", "Marley"), 20, listOf(Score("music", 5))), ), "year" to columnOf(2021, 2022), )

unfold

df.unfold { student }
df.unfold("student")

The new columns are named after the properties, in the order of the primary constructor (for a class without one, in the order of their names), and the column group has the name of the column it is made from. The other columns and the order of the columns stay the same. An object that is null gives null in every new column, except that a list property that becomes a FrameColumn gets an empty dataframe. The properties are those of the type of the column.

maxDepth

By default, the values of the properties stay as they are: name holds Name objects, and scores holds lists. With maxDepth = 1, nested objects become ColumnGroups, and lists of objects become FrameColumns; every further step goes one level deeper.

df.unfold(maxDepth = 1) { student }
df.unfold(maxDepth = 1) { col("student") }

Properties of a @DataSchema type, lists of them, DataRows, and DataFrames are always unfolded into column groups and frame columns, whatever maxDepth is.

Choosing properties

Pass the properties, roots, to make columns only for them:

df.unfold(Student::name, Student::age) { student }
df.unfold(Student::name, Student::age) { col("student") }

roots can also be getter-like functions, such as getX(). They only apply to a column that can be unfolded: a column of strings stays as it is even with String::length among roots.

With the compiler plugin, a call with roots gets an empty compile-time schema for now, so the result has no typed accessors.

Columns that stay as they are

A column that cannot be unfolded stays as it is. These are:

  • columns of simple values, such as numbers, strings, or enums;

  • columns of objects without public properties;

  • columns whose type is Any — for example, with objects of different classes; with unfold on DataColumn, only when the compiler sees the column as Any too;

  • ColumnGroups and FrameColumns.

unfold on DataColumn

Unfolds a single DataColumn and returns a ColumnGroup with the name of the column, or the column itself when it cannot be unfolded.

DataColumn.unfold(roots, maxDepth): DataColumn
df.student.unfold(maxDepth = 1)

The properties are those of the type of the column as the compiler sees it. When that type cannot be unfolded itself, such as Any? of an untyped column (df["student"]), the properties are those of the type of the column at runtime. A DataColumn<Student> is unfolded even when the type of the column at runtime is Any.

See also

  • toDataFrame() — builds a DataFrame from a list of objects by reading their properties.

  • flatten and ungroup — remove the column groups that unfold creates.

  • convert and replace — change the selected columns in any other way.

  • Don't confuse unfold with explode, which puts the elements of lists into separate rows.

15 October 2026