-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Null Safety
-
Section 4: Object-Oriented Kotlin
-
Section 5: Functional Kotlin
-
Section 6: Coroutines
-
Section 7: Collections Deep Dive
-
Section 8: Type System Deep Dive
-
Section 9: Interop and Tooling
-
Section 10: Kotlin DSLs and Patterns
-
Section 11: Testing and Quality
-
Section 12: Server-Side Kotlin
-
Section 13: Practical Projects
-
Section 14: Interview Practice
-
Section 15: More Practice Exercises
-
Section 16: More Standard Library
-
Section 17: Multiplatform Kotlin
-
Section 18: kotlin.collections In Depth
-
Section 19: kotlin.text In Depth
-
Section 20: kotlin.ranges and kotlin.sequences
-
Section 21: kotlin.io and File Handling
-
Section 22: kotlinx.coroutines Deep Dive
-
Section 23: kotlin.reflect
-
Section 24: Android Development with Kotlin Overview
-
Section 25: Kotlin Multiplatform Deep Dive
-
Section 26: Kotlin for Backend Deep Dive
-
Section 27: Kotlin Design Patterns
-
Section 28: Advanced Language Features
-
Section 29: More Practice Exercises
-
Section 30: More Interview Practice
-
Section 31: Kotlin Type System Deep Dive
-
Section 32: Kotlin Null Safety Advanced
-
Section 33: Kotlin Testing Deep Dive
-
Section 34: Kotlin Build Tooling Deep Dive
-
Section 35: Kotlin Serialization
-
Section 36: Kotlin Performance Considerations
-
Section 37: Kotlin Native Overview
-
Section 38: Kotlin for Data and Scripting
-
Section 39: More Coroutines Practice
-
Section 40: More Android-Adjacent Patterns
-
Section 41: More Practical Projects
-
Section 42: More Design and Architecture Practice
-
Section 43: Kotlin Language Evolution
-
Section 44: More Interview and Review
-
Section 45: Kotlin Delegation Patterns Deep Dive
-
Section 46: Kotlin Annotations Deep Dive
-
Section 47: Kotlin for Gradle Plugin Development
-
Section 48: Kotlin Concurrency Beyond Coroutines
-
Section 49: Kotlin Compiler Internals
-
Section 50: Real-World Kotlin Case Studies
-
Section 51: Final Practice Projects
-
Section 52: Kotlin for Server-Side Reactive Programming
-
Section 53: More Practice and Drills
-
Section 54: Kotlin Security Practices
177: Using Kotlin for Data Analysis with Kotlin DataFrame
If you've spent any time in the data science world, you've probably used Python's Pandas. It's powerful, but if you're a Kotlin developer, you know the pain of losing type safety the moment you move into data analysis. That's where the Kotlin DataFrame library comes in. It gives us a way to handle tabular data while keeping the compiler on our side.
How do I actually get data into a DataFrame without writing a bunch of boilerplate?
One of the things I love about this library is that it doesn't force you to define a huge set of POJOs just to read a CSV file. You can load data dynamically, and the library will infer the types for you. For this example, let's imagine we're analyzing a sales report for a small electronics store called "VoltGadgets".
import org.jetbrains.kotlinx.dataframe.DataFrame
import org.jetbrains.kotlinx.dataframe.io.readCSV
fun main() {
// I'm assuming you have a sales.csv with columns: Product, Category, Price, Quantity
val df = DataFrame.readCSV("sales.csv")
// Just printing the head to make sure it loaded correctly
df.head(5).print()
}
In a real-world project, you'd likely use this inside a Kotlin Notebook or a Jupyter notebook, where the dataframes render as beautiful interactive tables instead of just console text. But for a standard application, readCSV is your bread and butter.
I'm used to Pandas; how do I filter and transform columns in a type-safe way?
In Python, you often end up with "stringly-typed" code where you're passing column names as strings everywhere. In Kotlin, we have a few ways to handle this. While you can use strings, the library allows you to use a DSL that feels much more natural. Let's say we want to find all high-value sales (where the total is over $500) and create a new column for the total cost.
val highValueSales = df
.add("TotalCost") { "Price"() * "Quantity"() }
.filter { "TotalCost"() > 500.0 }
highValueSales.print()
Notice the "ColumnName"() syntax. This is a clever way the library handles type casting on the fly. I personally prefer this over creating a full data class for every single CSV I encounter, especially when the schema is huge or changes frequently.
How do I handle grouping and aggregations without getting lost in the syntax?
Grouping is where most data analysis happens. You want to know "What is the total revenue per category?" or "Which product is the best seller?". The groupBy function in Kotlin DataFrame is surprisingly intuitive. You group by one or more columns, and then you use aggregate to define what happens to the other columns.
val categorySummary = df
.groupBy("Category")
.aggregate {
sum("Quantity") into "TotalUnitsSold"
mean("Price") into "AveragePrice"
}
categorySummary.print()
The into keyword is the secret sauce here; it lets you name your resulting aggregation columns immediately. It keeps the pipeline clean and readable, so you don't have to chain five different renaming functions at the end of your script.
📋 Practical Task
Analyzing Electronics Inventory Value and Stock Alerts
You've been handed a CSV file named inventory.csv with the following columns: ItemName (String), Category (String), UnitPrice (Double), and StockLevel (Int).
Your task is to write a Kotlin script using the DataFrame library that performs the following operations:
- Load the
inventory.csvfile into a DataFrame. - Create a new column called
InventoryValueby multiplyingUnitPriceandStockLevel. - Filter the DataFrame to find "Critical Stock" items—those where the
StockLevelis less than 10. - Calculate the total
InventoryValuefor the entire store (a single sum of all items). - Group the data by
Categoryand find the averageUnitPricefor each category.
Expected Output: Your script should print the list of critical stock items and the final total inventory value of the store.
There are no comments for now.