Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Your Life on a Map: Private Geospatial Analytic...

Your Life on a Map: Private Geospatial Analytics with Kotlin DataFrame and Kandy

Avatar for Alexey Zinoviev

Alexey Zinoviev

May 27, 2026

More Decks by Alexey Zinoviev

Other Decks in Programming

Transcript

  1. Your Life on a Map: Private Geospatial Analytics with Kotlin

    DataFrame and Kandy Aleksei Zinovev Team Lead in Kotlin for Data Science
  2. About • Team Lead, Kotlin for Data Science • Geographical

    Data Fan • Math Enthusiast • Kotlin DataFrame Contributor • KotlinDL Author • Apache Ignite (in-memory database) PMC
  3. Why the App Is Not Enough • Single activity view

    only • No global map across activities
  4. Why the App Is Not Enough • Single activity view

    only • No global map across activities • Closed data storage
  5. Why the App Is Not Enough • Single activity view

    only • No global map across activities • Closed data storage • Export one track at a time
  6. Why the App Is Not Enough • Single activity view

    only • No global map across activities • Closed data storage • Export one track at a time
  7. What GPX Looks Like <trkpt lat="52.552857" lon="13.424176"> <time>2026-03-12T09:19:27.054Z</time> </trkpt> <trkpt

    lat="52.552812" lon="13.424094"> <time>2026-03-12T09:19:28.500Z</time> </trkpt>
  8. GPX → Kotlin val points = parseGPX(filePath) data class TrackPoint(

    val lat: Double, val lon: Double, val time: String, val altitude: Double? = null )
  9. GPX → DataFrame fun DataFrame.Companion.readGPX(filePath: String): DataFrame<*> { val points

    = parseGPX(filePath) return dataFrameOf( "lat" to points.map { it.lat }, "lon" to points.map { it.lon }, "time" to points.map { it.time }, "altitude" to points.map { it.altitude } )
  10. GPX → Kandy Plot val df = DataFrame.readGPX("walk1.gpx") val geoDataFrame

    = gpxDf.toGeoDataFrame() geoDataFrame.plot { geoPoints { color = Color.ORANGE } }
  11. GPX → Kandy Plot (Points + Polygons) val berlinBezirke =

    GeoDataFrame.readShapefile("Berlin_Bezirke.shp")
  12. GPX → Kandy Plot (Points + Polygons) val berlinBezirke =

    GeoDataFrame.readShapefile("Berlin_Bezirke.shp")
  13. GPX → Kandy Plot (Points + Polygons) berlinBezirke.plot { geoPolygon()

    withData(geoDataFrame) { geoPoints { size = 1.5 } } }
  14. Scaled Colored Bars With Kandy. Part I val byMonth =

    this.add("dur_hours") {(this["duration_minutes"] as Long).toDouble() / 60.0 } .groupBy { "month"<Int>() } .aggregate { sum { "dur_hours"<Double>() } into "total_hours" } .sortBy("month") .add("season") { when (this["month"] as Int) { 12, 1, 2 -> "Winter" 3, 4, 5 -> "Spring" 6, 7, 8 -> "Summer" else -> "Fall" }
  15. Scaled Colored Bars With Kandy. Part II bars { x("month")

    { axis.name = "Month" } y("total_hours") { axis.name = "Total Hours" } alpha = 0.85 fillColor("season") { scale = categorical( "Winter" to Color.hex("#5B9BD5"), "Spring" to Color.hex("#70AD47"), "Summer" to Color.hex("#FFC000"), "Fall" to Color.hex("#ED7D31") )
  16. Scaled Colored Bars With Kandy. Part III layout { title

    = "Walk Duration by Month (hours)" size = 1200 to 800 style { axis { text { fontSize = 25.0 } title { fontSize = 27.0 } } legend { text { fontSize = 25.0 } title { fontSize = 27.0 }
  17. Cleaning Strategy val smoothedDf = combinedDf .aggregatePointsByTime(intervalSeconds = 10) What

    happens inside: 1. Groups raw points into 10-sec windows 2. Averages lat/lon → recalculates speed
  18. Cleaning Strategy val smoothedDf = combinedDf .aggregatePointsByTime(intervalSeconds = 10) What

    happens inside: 1. Groups raw points into 10-sec windows 2. Averages lat/lon → recalculates speed 3. Spike 47 km/h → clean 4–6 km/h
  19. Your GPS History As A Heatmap In 4 steps •

    Count — split the map into a grid, count how many times you visited each cell
  20. Your GPS History As A Heatmap In 4 steps •

    Count — split the map into a grid, count how many times you visited each cell • Blur — spread each cell's heat to its neighbors (repeat 3×) — edges become smooth
  21. Your GPS History As A Heatmap In 4 steps •

    Count — split the map into a grid, count how many times you visited each cell • Blur — spread each cell's heat to its neighbors (repeat 3×) — edges become smooth • Log scale — so quiet streets don't disappear next to your favorite coffee shop
  22. Your GPS History As A Heatmap In 4 steps •

    Count — split the map into a grid, count how many times you visited each cell • Blur — spread each cell's heat to its neighbors (repeat 3×) — edges become smooth • Log scale — so quiet streets don't disappear next to your favorite coffee shop • Paint — blue (rarely visited) → green → yellow → red (your usual routes)
  23. createSmoothHeatmap Example Call walksDf.createSmoothHeatmap( shapefileDf = berlinWgs84, xRange = 13.08..13.73,

    yRange = 52.34..52.67, resolution = 200, blurMeters = 450.0, blurPasses = 3, )
  24. Tech Stack Summary • Kotlin DataFrame — data processing and

    transformations • Kandy — declarative visualization
  25. Tech Stack Summary • Kotlin DataFrame — data processing and

    transformations • Kandy — declarative visualization • dataframe-geo + JTS — geospatial DataFrames and polygon geometry
  26. Tech Stack Summary • Kotlin DataFrame — data processing and

    transformations • Kandy — declarative visualization • dataframe-geo + JTS — geospatial DataFrames and polygon geometry • GeoTools — coordinate system conversions (CRS / EPSG)
  27. Tech Stack Summary • Kotlin DataFrame — data processing and

    transformations • Kandy — declarative visualization • dataframe-geo + JTS — geospatial DataFrames and polygon geometry • GeoTools — coordinate system conversions (CRS / EPSG) • Ktor Client — HTTP calls to Open-Meteo weather API
  28. Tech Stack Summary • Kotlin DataFrame — data processing and

    transformations • Kandy — declarative visualization • dataframe-geo + JTS — geospatial DataFrames and polygon geometry • GeoTools — coordinate system conversions (CRS / EPSG) • Ktor Client — HTTP calls to Open-Meteo weather API • kotlinx-datetime — temporal operations
  29. Try It Yourself • Export your GPS data (GPX, KML,

    TCX formats) • Vibecode YourFileFormat to DataFrame read function • Use Kotlin DataFrame for processing • Enrich with Open-Meteo for weather • Visualize with Kandy
  30. Links • Private Geo Analytics Tutorial • Kandy Geo Tutorial

    • Geo Examples • DataFrame Docs • Data Analysis on Kotlin Site