# Access APIs

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

By nature, dataframes are dynamic objects; column labels depend on the input source, and new columns can be added or deleted while wrangling. Kotlin, in contrast, is a statically typed language where all types are defined and verified ahead of execution.

That's why creating a flexible, handy, and, at the same time, safe API to access dataframe columns is tricky.

In the Kotlin DataFrame library, we provide two different ways to access columns — the [String API](stringapi.html) and the [Extension Properties API](extensionpropertiesapi.html).

## String API

In the [String API](stringapi.html), columns are accessed by a `String` representing their name. Type-checking is done at runtime, name-checking too.

The most basic String API usage is quite intuitive and looks very similar to any other library working with dataframes:

```KOTLIN
// Get the "fullName" column
df["fullName"]

// Rename the "fullName" column to "name"
df.rename("fullName").to("name")
```

Also, you can create [String Column Accessors](stringapi.html#string-column-accessors) that can be used inside the [Columns Selection DSL](columnselectors.html) and [row expressions](datarow.html#row-expressions) using special methods:

```KOTLIN
// Select the "firstName" column from the "fullName" column group
// and the "age" column
df.select { "fullName"["firstName"]<String>() and "age"<Int>() }

// Takes only rows where the
// ("fullName"/"firstName") column value is equal to "Alice"
// and "age" column value is greater or equal to 18
df.filter {
    "fullName"["firstName"]<String>() == "Alice" && "age"<Int>() >= 18
}
```

Though the String API is the simpler of the two and doesn't require any additional setup, it lacks name- and type-safety; if column names or cast types are incorrect, a runtime exception will be thrown.

## Extension Properties API

The [Extension Properties API](extensionpropertiesapi.html) solves the main problems of the String API — name- and type-safety.

This is achieved by generating extension properties for `DataFrame<T>` (as well as for other related interfaces such as `DataRow` and others) based on its [data schema](schemas.html), which is represented by the type parameter `T`.

This requires the [Kotlin DataFrame Compiler Plugin](compiler-plugin.html), or alternatively, usage within the [Kotlin Notebook](setupkotlinnotebook.html).

> **Tip:**
> Extension Properties behavior differs in Kotlin Notebook and in the Kotlin DataFrame Compiler Plugin. [Read about it here](extensionpropertiesapi.html).

The same operations as in the String API can be performed via extension properties concisely and completely name- and typesafe:

```KOTLIN
// Get "fullName" column
df.fullName

// Rename "fullName" column to "name"
df.rename { fullName }.to("name")

// Select the "firstName" column from the "fullName" column group
// and the "age" column
df.select { fullName.firstName and age }

// Takes only rows where the
// ("fullName"/"firstName") column value is equal to "Alice"
// and "age" column value is greater or equal to 18
df.filter {
    fullName.firstName == "Alice" && age >= 18
}
```

## Comparing APIs

To better understand the distinction between the two Access APIs, let's look at a concise example of the DataFrame operations chain, presented using both APIs.

> **Note:**
> For most of the code snippets in this documentation, there's a tab selector that allows switching between Access APIs.

Extension Properties API:

```KOTLIN
val df =
    DataFrame.readCsv(
        "titanic.csv",
        delimiter = ';',
        parserOptions = ParserOptions(locale = Locale.GERMANY),
    )
```

```KOTLIN
df.add("lastName") { name.substringBefore(",") }
    .dropNulls { age and homedest }
    .filter { survived == 1 && homedest.endsWith("NY") && age in 10.0..20.0 }
```

String API:

```KOTLIN
DataFrame.readCsv(
    "titanic.csv",
    delimiter = ';',
    parserOptions = ParserOptions(locale = Locale.GERMANY),
)
    .add("lastName") { "name"<String>().substringBefore(",") }
    .dropNulls("age", "homedest")
    .filter {
        "survived"<Int>() == 1 &&
            "homedest"<String>().endsWith("NY") &&
            "age"<Double>() in 10.0..20.0
    }
```

> **Tip:**
> See the `titanic.csv` file on [GitHub](https://github.com/Kotlin/dataframe/blob/master/data/titanic.csv) or download it [here](https://kotlin.github.io/dataframe/resources/titanic.csv).

The Extension Properties API provides column names and types at compile-time, while the String API could be used with incorrect column names or types and break at runtime.

Additionally, when using [IntelliJ IDEA](https://www.jetbrains.com/idea/) with [Gradle](setupgradle.html#kotlin-dataframe-compiler-plugin) or [Maven](setupmaven.html#kotlin-dataframe-compiler-plugin) projects that have the [Kotlin DataFrame Compiler Plugin](compiler-plugin.html) enabled, as well as in [Kotlin Notebook](setupkotlinnotebook.html), code completion fully supports extension properties.

![Code Completion](images/codeCompletion.png)

However, note that after operations where the resulting columns cannot be inferred by the Compiler Plugin (for example, [pivot](pivot.html)), extension properties cannot be inferred automatically either. In such cases, you can use [cast](cast.html) to define a new data schema or switch to the String API.

|  API  |  Type-checking  |  Column names checking  |  Column existence checking  |  Code completion support  |
| --- | --- | --- | --- | --- |
|  String API  |  Runtime  |  Runtime  |  Runtime  |  No  |
|  Extension Properties API  |  Compile-time  |  Compile-time  |  Compile-time  |  Yes  |

