Примеры кода на Kotlin в Jupyter Notebook — различия между версиями
Woainikk (обсуждение | вклад) (→Построение графиков) |
м (rollbackEdits.php mass rollback) |
||
(не показано 17 промежуточных версий 3 участников) | |||
Строка 5: | Строка 5: | ||
'''Python:''' | '''Python:''' | ||
− | + | import numpy as np | |
− | + | # ...''' | |
− | + | a = np.ones((3, 3), dtype=int) * 3 | |
− | + | b = np.random.random((3, 3)) | |
− | + | b *= a '''# Success''' | |
− | + | a *= b '''# TypeError at runtime''' | |
'''Kotlin:''' | '''Kotlin:''' | ||
− | + | // ... | |
− | + | val a = ones<Int>(3, 3) * 3 | |
− | + | val b = Random.random(3, 3) | |
− | + | b *= a // '''Success''' | |
− | + | a *= b // '''Compilation error: ''' | |
'''//Type mismatch: inferred type is KtNDArray<Double> but KtNDArray<Int> was expected''' | '''//Type mismatch: inferred type is KtNDArray<Double> but KtNDArray<Int> was expected''' | ||
− | Также Котлин имеет имеет такую особенность дизайна языка, как ''null-safety'' и предоставляет такие операторы, как: ''safe call operator, elvis operator, not-null assertion operator'', что позволяет ему быть более типобезопасным, по | + | Также Котлин имеет имеет такую особенность дизайна языка, как ''null-safety'' и предоставляет такие операторы, как: ''safe call operator, elvis operator, not-null assertion operator'', что позволяет ему быть более типобезопасным, по сравнениюc с Python: |
− | |||
− | + | var a: String = "abc" | |
− | + | a = null //''' compilation error''' | |
− | + | var b: String? = "abc" | |
− | + | b = null // '''ok''' | |
Помимо функционального синтаксиса и конструкций, Котлин также предоставляет набор математических и machine learning библиотек, а также инструментов для Data Science, в том числе, интегрированность с Jupyter Notebook. | Помимо функционального синтаксиса и конструкций, Котлин также предоставляет набор математических и machine learning библиотек, а также инструментов для Data Science, в том числе, интегрированность с Jupyter Notebook. | ||
− | ==Kotlin в Jupyter Notebook== | + | ==Установка Kotlin в Jupyter Notebook== |
'''Kernel в Jupyter Notebook '''- это вычислительный движок, который исполняет код в данном документе и запускается автоматически при запуске ассоциированного с ним Jupyter Notebook документа. Они существуют для разных языков, например, ipython kernel исполняет Pythod код, а Kotlin kernel - Kotlin код в Jupyter Notebook. Именно '''Kotlin kernel''' позволяет писать и запускать код в Jupyter Notebook, а также использовать библиотеки и фреймворки, написанные на Java и Kotlin. | '''Kernel в Jupyter Notebook '''- это вычислительный движок, который исполняет код в данном документе и запускается автоматически при запуске ассоциированного с ним Jupyter Notebook документа. Они существуют для разных языков, например, ipython kernel исполняет Pythod код, а Kotlin kernel - Kotlin код в Jupyter Notebook. Именно '''Kotlin kernel''' позволяет писать и запускать код в Jupyter Notebook, а также использовать библиотеки и фреймворки, написанные на Java и Kotlin. | ||
Строка 41: | Строка 40: | ||
Обратите внимание, что Kotlin Jupyter требует установленной Java 8: | Обратите внимание, что Kotlin Jupyter требует установленной Java 8: | ||
apt-get install openjdk-8-jre | apt-get install openjdk-8-jre | ||
− | |||
==Поддерживаемые библиотеки== | ==Поддерживаемые библиотеки== | ||
− | * '''[https://github.com/thomasnield/kotlin-statistics kotlin-statistics | + | * '''[https://github.com/thomasnield/kotlin-statistics kotlin-statistics]''' - предоставляет расширения для функций для подсчета статистики. Поддерживает основные list/sequence/array functions, slicing operators (countBy, simpleRegressionBy, etc), binning operations, discrete PDF sampling, naive bayes classifier, clustering, linear regression, и другое |
− | * '''[https://github.com/mipt-npm/kmath kmath'''] | + | * '''[https://github.com/mipt-npm/kmath kmath'''] - поддерживает алгебраические структуры и операторы, математические выражения, гистограммы, потоковые операции, обертки над commons-math и koma, и другое. Вдохновлена numpy |
− | * '''[https://github.com/holgerbrandl/krangl Krangl'''] | + | * '''[https://github.com/holgerbrandl/krangl Krangl'''] - предоставляет функционал для обработки данных в функциональном стиле(filter, transform, aggregate, reshape и др.) Вдохновлена pandas |
− | * '''[https://github.com/JetBrains/lets-plot lets-plot | + | * '''[https://github.com/JetBrains/lets-plot lets-plot]''' - Мультиплатформенная библиотека для создания графиков из данных. Может использоваться не только в JVM, но также JS and Python. |
− | * '''[https://github.com/holgerbrandl/kravis kravis | + | * '''[https://github.com/holgerbrandl/kravis kravis]''' - библиотека для визуализации данных. |
− | * '''[https://github.com/cbeust/klaxon klaxon | + | * '''[https://github.com/cbeust/klaxon klaxon]''' $-$ Котлин JSON парсер |
− | * '''[https://github.com/apache/spark spark'''] | + | * '''[https://github.com/apache/spark spark'''] $-$ Фреймворк для распределённой обработки неструктурированных и слабоструктурированных данных |
− | * '''[https://github.com/eseifert/gral gral'''] | + | * '''[https://github.com/eseifert/gral gral'''] $-$ Java библиотека для отображения графиков |
− | * '''[https://koma.kyonifer.com/index.html koma'''] | + | * '''[https://koma.kyonifer.com/index.html koma'''] $-$ Котлин библиотека для научных вычислений |
− | * '''[https://github.com/Kotlin/kotlin-numpy numpy'''] | + | * '''[https://github.com/Kotlin/kotlin-numpy numpy'''] $-$ Kотлин обертка над Python NumPy |
− | * '''[https://github.com/JetBrains/Exposed exposed | + | * '''[https://github.com/JetBrains/Exposed exposed]''' $-$ Kотлин SQL фреймворк |
− | * '''[https://github.com/mysql/mysql-connector-j mysql'''] | + | * '''[https://github.com/mysql/mysql-connector-j mysql'''] $-$ MySql JDBC |
==Добавление зависимостей== | ==Добавление зависимостей== | ||
Строка 64: | Строка 62: | ||
'''Способы подключения зависимости:''' | '''Способы подключения зависимости:''' | ||
− | + | @file:Repository("https://jcenter.bintray.com") | |
− | + | @file:DependsOn("com.beust:klaxon:5.0.1") | |
− | + | import com.beust.klaxon.* | |
Или коротким способом: | Или коротким способом: | ||
Строка 79: | Строка 77: | ||
==Работа с JSON== | ==Работа с JSON== | ||
Пример парсинга датасета в формате JSON с Котлин библиотекой Klaxon: | Пример парсинга датасета в формате JSON с Котлин библиотекой Klaxon: | ||
− | + | %use klaxon | |
− | + | import java.io.* | |
− | + | data class User( | |
− | + | val age: Int, | |
− | + | val firstName: String ="", | |
− | + | val lastName: String ="", | |
− | + | val eyeColor: String | |
− | + | ) | |
− | + | val users = Klaxon().parseArray<User>(File("users.json").readText())!! | |
− | + | users.count() | |
==Функциональный стиль с библиотекой krangl== | ==Функциональный стиль с библиотекой krangl== | ||
− | Примеры обработки данных в функциональном стиле с Kotlin stdlib: | + | '''Примеры обработки данных в функциональном стиле с Kotlin stdlib:''' |
− | + | users.filter{it.eyeColor == "green"} | |
− | + | users.groupBy { user -> user.eyeColor } | |
− | + | .mapValues { mapEntry -> | |
− | + | mapEntry.value.map { user -> user.firstName} | |
− | + | } | |
'''Примеры обработки данных в функциональном стиле с krangl''' | '''Примеры обработки данных в функциональном стиле с krangl''' | ||
+ | |||
Используемые функции: | Используемые функции: | ||
* '''addColumn''' $-$ добавление новой вычисленной по заданной функции колонки | * '''addColumn''' $-$ добавление новой вычисленной по заданной функции колонки | ||
* '''filter ''' $-$ подвыборка строк по заданному условию: | * '''filter ''' $-$ подвыборка строк по заданному условию: | ||
− | + | df.filter { it["age"] eq 23 } | |
− | + | df.filter { it["weight"] gt 50 } | |
− | + | df.filter({ it["last_name"].isMatching { startsWith("Do") }}) | |
* '''sortedBy''' $-$ сортировка, можно передавать множество значений, которые будут учитываться в сортировке в соответствующем порядке | * '''sortedBy''' $-$ сортировка, можно передавать множество значений, которые будут учитываться в сортировке в соответствующем порядке | ||
− | + | df.sortedBy("age", "weight") | |
− | + | df.sortedByDescending("age") | |
* '''select и remove''' $-$ подвыборка строк | * '''select и remove''' $-$ подвыборка строк | ||
− | + | df.select2 { it is IntCol } // functional style column selection | |
− | + | df.select("last_name", "weight") // positive selection | |
− | + | df.remove("weight", "age") // negative selection | |
− | + | df.select({ endsWith("name") }) // selector mini-language | |
Обработка строк: | Обработка строк: | ||
− | + | fun readFromJsonString(s: String) = | |
− | + | s.removePrefix("JsonArray(value=[") | |
− | + | .removeSuffix("])") | |
− | + | .split(',') | |
− | + | .dropLastWhile{it.isEmpty()} | |
− | + | .toList() | |
− | + | val channels = DataFrame | |
− | + | .fromJson("channels.json") | |
− | + | .addColumn("groups") { it["groups"].map<String>{value -> readFromJsonString(value)}} | |
− | + | val modifiedChannels = channels | |
− | + | .addColumn("count"){it["groups"].map<List<*>>{it.count()}} | |
− | + | .filter{it["score"] gt 50} | |
− | + | .filter{it["age (y)"] lt 40} | |
− | + | .select("name", "score", "count", "groups") | |
− | + | .sortedByDescending("score") | |
+ | |||
+ | Больше примеров с ипользованием библиотеки krangl - https://github.com/Kotlin/kotlin-jupyter/blob/master/samples/Krangl.ipynb | ||
==Построение графиков== | ==Построение графиков== | ||
Строка 140: | Строка 141: | ||
Подробнее о настройках и параметрах графиков в Lets-plot: https://github.com/JetBrains/lets-plot-kotlin/blob/master/docs/guide/user_guide.ipynb | Подробнее о настройках и параметрах графиков в Lets-plot: https://github.com/JetBrains/lets-plot-kotlin/blob/master/docs/guide/user_guide.ipynb | ||
− | + | lets_plot(eyes) + stat_count() + ggsize(500,300) | |
[[Файл:I04n3zFx68s.jpg |600px|thumb|center|]] | [[Файл:I04n3zFx68s.jpg |600px|thumb|center|]] | ||
+ | val rand = java.util.Random() | ||
− | + | val data = mapOf<String, Any>( | |
− | + | "rating" to List(200) { rand.nextGaussian() } + List(200) { rand.nextGaussian() * 1.5 + 1.5 }, | |
− | + | "cond" to List(200) { "A" } + List(200) { "B" } | |
− | + | ) | |
− | + | var p = lets_plot(data) | |
− | + | p += geom_density(color="dark_green", alpha=.3) {x="rating"; fill="cond"} | |
− | + | p + ggsize(500, 250) | |
− | |||
[[Файл:2-_1xADOor0.jpg |700px|thumb|center|]] | [[Файл:2-_1xADOor0.jpg |700px|thumb|center|]] | ||
− | + | lets_plot(mapOf( | |
− | + | "date" to usages.select("DateTime").collectAsList().map{(it[0] as Timestamp).getTime()}, | |
− | + | "usage" to usages.select("users").collectAsList().map{it[0]} | |
− | + | )) +''' | |
− | + | geom_bar(stat = Stat.identity){x = "date"; y = "usage"; fill ="usage"} + | |
− | + | scale_x_datetime() + | |
− | + | scale_fill_hue()+ | |
− | + | qqsize(800, 400) | |
[[Файл:YG1W2uqtTSc.jpg |700px|thumb|center|]] | [[Файл:YG1W2uqtTSc.jpg |700px|thumb|center|]] | ||
Строка 169: | Строка 170: | ||
'''Библиотека Kravis''' | '''Библиотека Kravis''' | ||
− | + | ||
− | + | Подробнее - https://github.com/holgerbrandl/kravis | |
− | + | ||
− | + | %use kravis, krangl ''' | |
− | + | val sleepData = DataFrame.fromJson("data.json"). | |
− | + | .addColumn("rem_proportion") { it["sleep_rem"] / it["sleep_total"] } | |
− | + | .plot(x = "sleep_total", y = "rem_proportion", color = "vore", size = "brainwt") | |
+ | .geomPoint(alpha = 0.7) | ||
+ | .guides(size = LegendType.none) | ||
+ | .title("Correlation between dream and total sleep time") | ||
[[Файл:YKNvj0bWuO8.jpg |700px|thumb|center|]] | [[Файл:YKNvj0bWuO8.jpg |700px|thumb|center|]] | ||
Строка 189: | Строка 193: | ||
# [https://github.com/Kotlin/kotlin-jupyter/tree/master/samples Примеры kotlin-jupyter] | # [https://github.com/Kotlin/kotlin-jupyter/tree/master/samples Примеры kotlin-jupyter] | ||
# [https://www.youtube.com/watch?v=APnyDVye4JA KotlinConf 2019: Using Kotlin for Data Science] | # [https://www.youtube.com/watch?v=APnyDVye4JA KotlinConf 2019: Using Kotlin for Data Science] | ||
+ | |||
+ | [[Категория: Машинное обучение]] [[Категория: Примеры кода]] |
Текущая версия на 19:40, 4 сентября 2022
Содержание
Kotlin и Data Science
Kotlin - это прагматичный, статически типизированный JVM язык, который поддерживает написание кода как в ООП, так и в функциональном стилях, а также компилируется в различные платформы: JVM, JS, Native. Благодаря статической типизации, Котлин более производителен в больших проектах, по сравнению с Python, а также позволяет избежать Runtime errors. Сравним аналогичные примеры кода на Python и Kotlin:
Python:
import numpy as np # ... a = np.ones((3, 3), dtype=int) * 3 b = np.random.random((3, 3)) b *= a # Success a *= b # TypeError at runtime
Kotlin:
// ... val a = ones<Int>(3, 3) * 3 val b = Random.random(3, 3) b *= a // Success a *= b // Compilation error: //Type mismatch: inferred type is KtNDArray<Double> but KtNDArray<Int> was expected
Также Котлин имеет имеет такую особенность дизайна языка, как null-safety и предоставляет такие операторы, как: safe call operator, elvis operator, not-null assertion operator, что позволяет ему быть более типобезопасным, по сравнениюc с Python:
var a: String = "abc" a = null // compilation error var b: String? = "abc" b = null // ok
Помимо функционального синтаксиса и конструкций, Котлин также предоставляет набор математических и machine learning библиотек, а также инструментов для Data Science, в том числе, интегрированность с Jupyter Notebook.
Установка Kotlin в Jupyter Notebook
Kernel в Jupyter Notebook - это вычислительный движок, который исполняет код в данном документе и запускается автоматически при запуске ассоциированного с ним Jupyter Notebook документа. Они существуют для разных языков, например, ipython kernel исполняет Pythod код, а Kotlin kernel - Kotlin код в Jupyter Notebook. Именно Kotlin kernel позволяет писать и запускать код в Jupyter Notebook, а также использовать библиотеки и фреймворки, написанные на Java и Kotlin.
На данный момент, установить Kotlin kernel можно только через conda:
conda install kotlin-jupyter-kernel -c jetbrains
Обратите внимание, что Kotlin Jupyter требует установленной Java 8:
apt-get install openjdk-8-jre
Поддерживаемые библиотеки
- kotlin-statistics - предоставляет расширения для функций для подсчета статистики. Поддерживает основные list/sequence/array functions, slicing operators (countBy, simpleRegressionBy, etc), binning operations, discrete PDF sampling, naive bayes classifier, clustering, linear regression, и другое
- kmath - поддерживает алгебраические структуры и операторы, математические выражения, гистограммы, потоковые операции, обертки над commons-math и koma, и другое. Вдохновлена numpy
- Krangl - предоставляет функционал для обработки данных в функциональном стиле(filter, transform, aggregate, reshape и др.) Вдохновлена pandas
- lets-plot - Мультиплатформенная библиотека для создания графиков из данных. Может использоваться не только в JVM, но также JS and Python.
- kravis - библиотека для визуализации данных.
- klaxon $-$ Котлин JSON парсер
- spark $-$ Фреймворк для распределённой обработки неструктурированных и слабоструктурированных данных
- gral $-$ Java библиотека для отображения графиков
- koma $-$ Котлин библиотека для научных вычислений
- numpy $-$ Kотлин обертка над Python NumPy
- exposed $-$ Kотлин SQL фреймворк
- mysql $-$ MySql JDBC
Добавление зависимостей
По умолчанию возможно добавлять зависимости из следующих репозиториев:
Способы подключения зависимости:
@file:Repository("https://jcenter.bintray.com") @file:DependsOn("com.beust:klaxon:5.0.1") import com.beust.klaxon.*
Или коротким способом:
%use klaxon
Также можно указать конкретную версию зависимости:
%use krangl(0.10)
Можно указать свойства library descriptor (обязательно использовать именованные аргументы):
%use spark(scala=2.11.10, spark=2.4.2)
Подключить несколько библиотек одним выражением:
%use lets-plot, krangl, mysql(8.0.15)
Работа с JSON
Пример парсинга датасета в формате JSON с Котлин библиотекой Klaxon:
%use klaxon import java.io.*
data class User( val age: Int, val firstName: String ="", val lastName: String ="", val eyeColor: String )
val users = Klaxon().parseArray<User>(File("users.json").readText())!! users.count()
Функциональный стиль с библиотекой krangl
Примеры обработки данных в функциональном стиле с Kotlin stdlib:
users.filter{it.eyeColor == "green"}
users.groupBy { user -> user.eyeColor } .mapValues { mapEntry -> mapEntry.value.map { user -> user.firstName} }
Примеры обработки данных в функциональном стиле с krangl
Используемые функции:
- addColumn $-$ добавление новой вычисленной по заданной функции колонки
- filter $-$ подвыборка строк по заданному условию:
df.filter { it["age"] eq 23 } df.filter { it["weight"] gt 50 } df.filter({ it["last_name"].isMatching { startsWith("Do") }})
- sortedBy $-$ сортировка, можно передавать множество значений, которые будут учитываться в сортировке в соответствующем порядке
df.sortedBy("age", "weight") df.sortedByDescending("age")
- select и remove $-$ подвыборка строк
df.select2 { it is IntCol } // functional style column selection df.select("last_name", "weight") // positive selection df.remove("weight", "age") // negative selection df.select({ endsWith("name") }) // selector mini-language
Обработка строк:
fun readFromJsonString(s: String) = s.removePrefix("JsonArray(value=[") .removeSuffix("])") .split(',') .dropLastWhile{it.isEmpty()} .toList()
val channels = DataFrame .fromJson("channels.json") .addColumn("groups") { it["groups"].map<String>{value -> readFromJsonString(value)}}
val modifiedChannels = channels .addColumn("count"){it["groups"].map<List<*>>{it.count()}} .filter{it["score"] gt 50} .filter{it["age (y)"] lt 40} .select("name", "score", "count", "groups") .sortedByDescending("score")
Больше примеров с ипользованием библиотеки krangl - https://github.com/Kotlin/kotlin-jupyter/blob/master/samples/Krangl.ipynb
Построение графиков
Lets-plot
Подробнее о настройках и параметрах графиков в Lets-plot: https://github.com/JetBrains/lets-plot-kotlin/blob/master/docs/guide/user_guide.ipynb
lets_plot(eyes) + stat_count() + ggsize(500,300)
val rand = java.util.Random()
val data = mapOf<String, Any>( "rating" to List(200) { rand.nextGaussian() } + List(200) { rand.nextGaussian() * 1.5 + 1.5 }, "cond" to List(200) { "A" } + List(200) { "B" } ) var p = lets_plot(data) p += geom_density(color="dark_green", alpha=.3) {x="rating"; fill="cond"} p + ggsize(500, 250)
lets_plot(mapOf( "date" to usages.select("DateTime").collectAsList().map{(it[0] as Timestamp).getTime()}, "usage" to usages.select("users").collectAsList().map{it[0]} )) + geom_bar(stat = Stat.identity){x = "date"; y = "usage"; fill ="usage"} + scale_x_datetime() + scale_fill_hue()+ qqsize(800, 400)
Библиотека Kravis
Подробнее - https://github.com/holgerbrandl/kravis
%use kravis, krangl val sleepData = DataFrame.fromJson("data.json"). .addColumn("rem_proportion") { it["sleep_rem"] / it["sleep_total"] } .plot(x = "sleep_total", y = "rem_proportion", color = "vore", size = "brainwt") .geomPoint(alpha = 0.7) .guides(size = LegendType.none) .title("Correlation between dream and total sleep time")
Библиотека Gral
Источники
- Kotlinlang — Официальный сайт языка Kotlin
- Kotlin For Python Developers Documentation — Документация языка Kotlin для разработчиков на Python
- kotlin-jupyter on GitHub
- Примеры kotlin-jupyter
- KotlinConf 2019: Using Kotlin for Data Science