# Interop with Collections

> For the complete documentation index, see [llms.txt](https://kotlin.github.io/dataframe/llms.txt).

Kotlin DataFrame and Kotlin Collection represent two different approaches to data storage:

* [DataFrame](dataframe.html) stores data by fields/columns

* `Collection` stores data by records/rows

API reference: [api package](https://kotlin.github.io/dataframe/api-docs/core/org.jetbrains.kotlinx.dataframe.api/index.html)

Although [DataFrame](dataframe.html) doesn't implement the [Collection](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-collection/#kotlin.collections.Collection) or [Iterable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-iterable/) interface, it has many similar operations, such as [filter](filter.html), [take](slicerows.html#take), [first](first.html), [map](map.html), [groupBy](groupby.html) etc.

[DataFrame](dataframe.html) has two-way compatibility with [Map](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-map/) and [List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/):

* `List<T>` -> `DataFrame<T>`: [toDataFrame](createdataframe.html#dataframe-from-iterable-t)

* `DataFrame<T>` -> `List<T>`: [toList](tolist.html)

* `Map<String, List<*>>` -> `DataFrame<*>`: [toDataFrame](createdataframe.html#dataframe-from-map-string-list)

* `DataFrame<*>` -> `Map<String, List<*>>`: [toMap](tomap.html)

* `List<List<T>>` -> `DataFrame<*>`: [toDataFrame](createdataframe.html#dataframe-from-list-list-t)

Columns, rows, and values of [DataFrame](dataframe.html) can be accessed as [List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/), [Iterable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-iterable/) and [Sequence](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/-sequence/) accordingly:

```KOTLIN
df.columns() // List<DataColumn>
df.rows() // Iterable<DataRow>
df.values() // Sequence<Any?>
```

## Interop with data classes

[DataFrame](dataframe.html) can be used as an intermediate object for transformation from one data structure to another.

Assume you have a list of instances of some [data class](https://kotlinlang.org/docs/data-classes.html) that you need to transform into some other format.

```KOTLIN
data class Input(val a: Int, val b: Int)

val list = listOf(Input(1, 2), Input(3, 4))
```

You can convert this list into [DataFrame](dataframe.html) using [toDataFrame()](createdataframe.html#todataframe) extension:

```KOTLIN
val df = list.toDataFrame()
```

Mark the original data class with [DataSchema](schemas.html) annotation to get [extension properties](extensionpropertiesapi.html) and perform data transformations.

```KOTLIN
@DataSchema
data class Input(val a: Int, val b: Int)

val df2 = df.add("c") { a + b }
```

> **Tip:**
> To enable extension properties generation, you should use the [DataFrame plugin](schemasgradle.html) for Gradle or the [Kotlin Jupyter kernel](setupjupyter.html)

After your data is transformed, [DataFrame](dataframe.html) instances can be exported eagerly into [List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/) of another data class using [toListOf](tolist.html#tolistof):

```KOTLIN
data class Output(val a: Int, val b: Int, val c: Int)

val result = df2.toListOf<Output>()
```

`toListOf` works no matter what the type argument of the [DataFrame](dataframe.html) is, so use it in most cases. [toList](tolist.html#tolist) creates instances of the type argument itself, so use it only when this type argument is known to be a data class. With the [compiler plugin](compiler-plugin.html), this is not the case here: the plugin gives `df2` a generated type argument, which is not a data class, so `df2.toList()` throws.

A [ColumnGroup](datacolumn.html#columngroup) becomes a nested data class:

```KOTLIN
val df = dataFrameOf("name", "lastName", "age")("John", "Doe", 21)
    .group("name", "lastName").into("fullName")

data class FullName(val name: String, val lastName: String)

data class Person(val fullName: FullName, val age: Int)

val persons = df.toListOf<Person>() // [Person(fullName=FullName(name=John, lastName=Doe), age=21)]
```

Alternatively, [toSequence and toSequenceOf](tolist.html#tosequence-and-tosequenceof) create a lazy [Sequence](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/-sequence/). The objects are created only when the sequence is iterated, so you do not need to hold all of them in memory at once.

The rules for matching columns to data class properties are in [How rows become objects](tolist.html#how-rows-become-objects).

### Converting columns with object instances to ColumnGroup

[unfold](unfold.html) turns columns of objects inside an existing dataframe into [ColumnGroup](datacolumn.html#columngroup)s, the way [toDataFrame()](createdataframe.html#todataframe) builds a dataframe from a list of objects.

