# Kotlin 用于数据科学
![](https://img.kancloud.cn/4d/d8/4dd85d0d59d8c66fa58c85f05c44d4bf_1440x840.png)
数据科学在信息技术中具有特殊地位:它同时包含软件开发与科学研究两方面。作为一门学科,数据科学涵盖了广泛的领域:数据工程、数据分析、机器学习、可视化等等。
为了涵盖所有这些不同领域,软件行业有许多用于数据科学的技术与工具。其中包含框架、特定的 IDE(称为*notebook*)、绘图工具以及专为数据分析与数学研究设计的编程语言。
通用语言也可以应用于数据科学领域,而 Kotlin 已经为数据科学所采用。在此我们会介绍一些关于将 Kotlin 用于数据科学时的实用知识。
## 工具
现代软件开发人员很少会在纯文本编辑器中编写代码并在命令行运行。相反,大家倾向于使用可以在一个工具中处理所有开发任务的集成开发环境(IDE,Integrated Development Environment)。数据科学家也有类似的工具,称为 *notebook*。notebook 让用户可以进行研究并将其存储在单个环境中。在一个 notebook 中,可以在代码旁编写叙述性文本、执行代码块及以任何所需格式(输出文本、表格、数据可视化等等)查看结果。
Kotlin 提供了与两个流行的 notebook 的集成:Jupyter 与 Apache Zeppelin,它们都支持编写及运行 Kotlin 代码块。
### Jupyter 内核
开源项目 [Jupyter](https://jupyter.org/) 提供了著名的基于 web 的开发环境 **Jupyter Notebook**。对于代码执行,Jupyter 使用*内核*的概念——独立运行的不同组件,并且这些组件根据请求执行代码,例如,当在一个 notebook 中点击 **Run** 时。
Jupyter 团队维护了一个内核——运行 Python 代码的 IPython。但是,还有其他社区维护的用于不同语言的各种内核。
其中包括**用于 Jupyter notbook 的 Kotlin 内核**。有了这个内核,就可以在 Jupyter notebook 中编写并运行 Kotlin 代码,以及使用以 Java 或 Kotlin 编写的第三方数据科学框架。
#### 设置 Kotlin 内核
Kotlin 内核需要安装 Java 8。
请使用 [Conda](https://docs.conda.io/projects/conda/en/latest/) 安装该内核:
```bash
conda install kotlin-jupyter-kernel -c jetbrains
```
一旦内核安装完毕,就可以运行 Jupyter notebook 并切换到 Kotlin 内核。仅此而已,然后就可以在 notebook 中编写并运行 Kotlin 了!
![](https://img.kancloud.cn/12/3f/123f73bf621ec2d97b06c8f7f669dd83_1190x383.png)
可以在[这里](https://github.com/cheptsov/kotlin-jupyter-demo/blob/master/index.ipynb)找到关于 Jupyter 的 Kotlin 内核的更多信息。
### Zeppelin 解释器
[Apache Zeppelin](http://zeppelin.apache.org/) 是一个流行的基于 web 的交互式数据分析解决方案。Zeppelin 为 [Apache Spark](http://zeppelin.apache.org/docs/latest/interpreter/spark.html)集群计算系统提供了强大的支持,这对于数据工程特别有用。Spark 提供了多种语言的高级 API。
Zeppelin 中的语言支持由*解释器*提供,解释器是让用户能够使用指定语言或者数据处理后端的插件。对于不同的编程语言有许多社区维护的解释器。我们提供了增加 Kotlin 支持的**用于 Apache Zeppelin 的 Kotlin 解释器**。
#### 设置带 Kotlin 解释器的 Zeppelin
目前,最新版本的 Zeppelin(0.8.2)并未内置 Kotlin 解释器。不过,在 Zeppelin 的 master 分支中有。因此,为了向 Zeppelin 添加 Kotlin 支持,需要从源代码构建自己的版本。
构建 Zeppelin 的定制版需要:
* [Git](https://git-scm.com/)
* [Maven](https://maven.apache.org/install.html),
* [JDK 8](https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
* 列在[此处](https://zeppelin.apache.org/docs/latest/setup/basics/how_to_build.html#build-requirements)各项依赖
首先,从 Zeppelin 版本库中检出 master 分支:
```bash
git clone --depth=1 git@github.com:apache/zeppelin.git
```
或者
```bash
git clone --depth=1 https://github.com/apache/zeppelin.git
```
使用 Maven 构建 Zeppelin,请切换到 Zeppelin 目录并运行以下命令:
```bash
mvn clean package -DskipTests -Pspark-2.4 -Pscala-2.11
```
然后使用以下命令运行 Zeppelin:
```bash
./bin/zeppelin-daemon.sh start
```
现在可以在 `http://localhost:8089` 打开 Zeppelin UI 了。
如需了解如何在 Spark 集群中部署带 Kotlin 支持的 Zeppelin,请参见[这个说明](/docs/tutorials/zeppelin-spark-cluster.html)。
## 相关库
对于软件工程来说,任何领域的重要组成部分都有相关领域框架的可用性。对于数据科学,包括诸如机器学习、数据分析、可视化等领域。幸运的是,已经有很多用 Kotlin 编写的数据科学框架。更完美的是还有更多用 Java 编写的框架,因为可以在 Kotlin 代码中无缝调用 Java 框架。
以下是可能对数据科学有用的库的两个简短列表。
### Kotlin 库
* [kotlin-statistics](https://github.com/thomasnield/kotlin-statistics) 是一个为探索性统计与生产统计中提供扩展函数的库。它支持基本的数字列表/序列/数组函数(从 `sum` 到 `skewness`)、切片操作符(诸如 `countBy`、 `simpleRegressionBy`)、分箱(binning)操作符、离散 PDF 采样、朴素贝叶斯分类器、聚类、线性回归等等。
* [kmath](https://github.com/mipt-npm/kmath) 是一个受 [NumPy](https://numpy.org/) 启发的库。这个库支持代数结构与运算、类数组结构、数学表达式、直方图、流运算、[commons-math](http://commons.apache.org/proper/commons-math/) 与[koma](https://github.com/kyonifer/koma) 的包装等等。
* [krangl](https://github.com/holgerbrandl/krangl) 是一个受 R 语言的 [dplyr](https://dplyr.tidyverse.org/)与 Python 的 [pandas](https://pandas.pydata.org/) 启发的库。这个库提供了采用函数式风格 API进行数据操作的功能;它还包括过滤、转换、聚合与重塑表格数据的函数。
* [lets-plot](https://github.com/JetBrains/lets-plot) 是一个用 Kotlin 编写的统计数据绘图库。Lets-Plot 是多平台的,不仅可以用于 JVM,还可以用于 JS 与 Python。更多信息请参见[下文](#lets-plot-for-kotlin)。
* [kravis](https://github.com/holgerbrandl/kravis) 是另一个用于表格数据可视化的库,其灵感来自于Python 的 [ggplot](https://ggplot2.tidyverse.org/)。
### Java 库
因为 Kotlin 提供了与 Java 互操作的头等支持,所以也可以在用于数据科学的 Kotlin 代码中使用 Java 库。
以下是这些库的一些示例:
* [DeepLearning4J](https://deeplearning4j.org/)——一个 Java 深度学习库
* [ND4J](http://nd4j.org/)——用于 JVM 的高效矩阵数学库
* [Dex](https://github.com/PatMartin/Dex)——一个基于 Java 的数据可视化工具
* [Smile](https://github.com/haifengl/smile)——一个全面的机器学习、自然语言处理、线性代数、图、插值与可视化系统
* [Apache Commons Math](http://commons.apache.org/proper/commons-math/)——一个 Java 通用数学、统计与机器学习库
* [OptaPlanner](https://www.optaplanner.org/)——一个用于优化规划问题的求解器实用程序
* [Charts](https://github.com/HanSolo/charts)——一个正在开发中的科学 JavaFX 图表库
* [CoreNLP](https://stanfordnlp.github.io/CoreNLP/)——一个自然语言处理工具包
* [Apache Mahout](https://mahout.apache.org/)——一个回归、聚类与推荐的分布式框架
* [Weka](https://www.cs.waikato.ac.nz/ml/index.html)——一组用于数据挖掘任务的机器学习算法
如果这个列表还不能满足需求,可以在 Thomas Nield 的[**Kotlin 数据科学资源**](https://github.com/thomasnield/kotlin-data-science-resources)摘要中找到更多选项。
### Lets-Plot for Kotlin
**Lets-Plot for Kotlin** 是 [Lets-Plot](https://github.com/JetBrains/lets-plot) 库的 Kotlin API, Lets-Plot 是一个完全用 Kotlin 编写的开源的统计数据绘图库。Lets-Plot 建立在分层图形的概念上,该概念首先在 Leland Wilkinson 的著作 [The Grammar of Graphics](https://www.goodreads.com/book/show/2549408.The_Grammar_of_Graphics)中描述,后来在 R 语言的 [ggplot2](https://ggplot2.tidyverse.org/) 包中实现。
Lets-Plot for Kotlin 与[用于 Jupyter notebook 的 Kotlin 内核](http://www.kotlincn.net/docs/reference/data-science-overview.html#jupyter-%E5%86%85%E6%A0%B8)紧密集成。安装并启用 Kotlin 内核后,将以下行添加到 Jupyter notebook 中:
```
%use lets-plot
```
就是这样,现在就可以调用 Lets-Plot 中的函数并查看结果了。
![](https://img.kancloud.cn/0b/a0/0ba0bfc8f2f4b43a7e71b04c0228bfab_2797x1513.png)
### NumPy 的 Kotlin 绑定
[**KNumpy**](https://github.com/kotlin/kotlin-numpy/)(**NumPy 的 Kotlin 绑定**)是一个能让 Kotlin 代码调用 NumPy 函数的 Kotlin 库。[NumPy](https://numpy.org/)是使用 Python 进行科学计算的一个流行软件包。它为多维数组处理、线性代数、傅立叶变换、随机数以及其他数学任务提供了强大的功能。
KNumpy 为 NumPy 函数提供了静态类型的包装。由于 Kotlin 的函数式能力,KNumpy 的 API 与对应的 NumPy API 非常相似。这让有 NumPy 经验的开发人员可以轻松切换到 KNumpy。
以下是两份等价代码的示例:
```python
# Python
import numpy as np
a = np.arange(15).reshape(3, 5)
print(a.shape == (3, 5)) # True
print(a.ndim == 2) # True
print(a.dtype.name) # 'int64'
b = (np.arange(15) ** 2).reshape(3, 5)
```
```kotlin
// Kotlin
import org.jetbrains.numkt.*
fun main() {
val a = arange(15).reshape(3, 5)
println(a.shape.contentEquals(intArrayOf(3, 5))) // true
println(a.ndim == 2) // true
println(a.dtype) // class java.lang.Integer
// 创建一个整型数组,我们将每个元素取平方,然后重塑为 (3, 5)
val b = (arange(15) `**` 2).reshape(3, 5)
}
```
与 Python 不同的是,Kotlin 是一种静态类型语言。这样使用 KNumpy 就可以避免运行时的类型错误:
Kotlin 编译器会在更早的阶段检测到相应问题。
```python
# Python
import numpy as np
a = np.ones((3, 3), dtype=int) * 3
b = np.random.random((3, 3))
b *= a # 成功
a *= b # 运行时 TypeError
```
```kotlin
// Kotlin
// ……
val a = ones<Int>(3, 3) * 3
val b = Random.random(3, 3)
b *= a // 成功
a *= b // 编译错误:
// Type mismatch: inferred type is KtNDArray<Double> but KtNDArray<Int> was expected
```
</div>
- 前言
- Kotlin简介
- IntelliJ IDEA技巧总结
- idea设置类注释和方法注释模板
- 像Android Studion一样创建工程
- Gradle
- Gradle入门
- Gradle进阶
- 使用Gradle创建一个Kotlin工程
- 环境搭建
- Androidstudio平台搭建
- Eclipse的Kotlin环境配置
- 使用IntelliJ IDEA
- Kotlin学习路线
- Kotlin官方中文版文档教程
- 概述
- kotlin用于服务器端开发
- kotlin用于Android开发
- kotlin用于JavaScript开发
- kotlin用于原生开发
- Kotlin 用于数据科学
- 协程
- 多平台
- 新特性
- 1.1的新特性
- 1.2的新特性
- 1.3的新特性
- 开始
- 基本语法
- 习惯用法
- 编码规范
- 基础
- 基本类型
- 包与导入
- 控制流
- 返回与跳转
- 类与对象
- 类与继承
- 属性与字段
- 接口
- 可见性修饰符
- 扩展
- 数据类
- 密封类
- 泛型
- 嵌套类
- 枚举类
- 对象
- 类型别名
- 内嵌类
- 委托
- 委托属性
- 函数与Lambda表达式
- 函数
- Lambda表达式
- 内联函数
- 集合
- 集合概述
- 构造集合
- 迭代器
- 区间与数列
- 序列
- 操作概述
- 转换
- 过滤
- 加减操作符
- 分组
- 取集合的一部分
- 取单个元素
- 排序
- 聚合操作
- 集合写操作
- List相关操作
- Set相关操作
- Map相关操作
- 多平台程序设计
- 平台相关声明
- 以Gradle创建
- 更多语言结构
- 解构声明
- 类型检测与转换
- This表达式
- 相等性
- 操作符重载
- 空安全
- 异常
- 注解
- 反射
- 作用域函数
- 类型安全的构造器
- Opt-in Requirements
- 核心库
- 标准库
- kotlin.test
- 参考
- 关键字与操作符
- 语法
- 编码风格约定
- Java互操作
- Kotlin中调用Java
- Java中调用Kotlin
- JavaScript
- 动态类型
- kotlin中调用JavaScript
- JavaScript中调用kotlin
- JavaScript模块
- JavaScript反射
- JavaScript DCE
- 原生
- 并发
- 不可变性
- kotlin库
- 平台库
- 与C语言互操作
- 与Object-C及Swift互操作
- CocoaPods集成
- Gradle插件
- 调试
- FAQ
- 协程
- 协程指南
- 基础
- 取消与超时
- 组合挂起函数
- 协程上下文与调度器
- 异步流
- 通道
- 异常处理与监督
- 共享的可变状态与并发
- Select表达式(实验性)
- 工具
- 编写kotlin代码文档
- 使用Kapt
- 使用Gradle
- 使用Maven
- 使用Ant
- Kotlin与OSGI
- 编译器插件
- 编码规范
- 演进
- kotlin语言演进
- 不同组件的稳定性
- kotlin1.3的兼容性指南
- 常见问题
- FAQ
- 与Java比较
- 与Scala比较(官方已删除)
- Google开发者官网简介
- Kotlin and Android
- Get Started with Kotlin on Android
- Kotlin on Android FAQ
- Android KTX
- Resources to Learn Kotlin
- Kotlin样品
- Kotlin零基础到进阶
- 第一阶段兴趣入门
- kotlin简介和学习方法
- 数据类型和类型系统
- 入门
- 分类
- val和var
- 二进制基础
- 基础
- 基本语法
- 包
- 示例
- 编码规范
- 代码注释
- 异常
- 根类型“Any”
- Any? 可空类型
- 可空性的实现原理
- kotlin.Unit类型
- kotlin.Nothing类型
- 基本数据类型
- 数值类型
- 布尔类型
- 字符型
- 位运算符
- 变量和常量
- 语法和运算符
- 关键字
- 硬关键字
- 软关键字
- 修饰符关键字
- 特殊标识符
- 操作符和特殊符号
- 算术运算符
- 赋值运算符
- 比较运算符
- 逻辑运算符
- this关键字
- super关键字
- 操作符重载
- 一元操作符
- 二元操作符
- 字符串
- 字符串介绍和属性
- 字符串常见方法操作
- 字符串模板
- 数组
- 数组介绍创建及遍历
- 数组常见方法和属性
- 数组变化以及下标越界问题
- 原生数组类型
- 区间
- 正向区间
- 逆向区间
- 步长
- 类型检测与类型转换
- is、!is、as、as-运算符
- 空安全
- 可空类型变量
- 安全调用符
- 非空断言
- Elvis操作符
- 可空性深入
- 可空性和Java
- 函数
- 函数式编程概述
- OOP和FOP
- 函数式编程基本特性
- 组合与范畴
- 在Kotlin中使用函数式编程
- 函数入门
- 函数作用域
- 函数加强
- 命名参数
- 默认参数
- 可变参数
- 表达式函数体
- 顶层、嵌套、中缀函数
- 尾递归函数优化
- 函数重载
- 控制流
- if表达式
- when表达式
- for循环
- while循环
- 循环中的 Break 与 continue
- return返回
- 标签处返回
- 集合
- list集合
- list集合介绍和操作
- list常见方法和属性
- list集合变化和下标越界
- set集合
- set集合介绍和常见操作
- set集合常见方法和属性
- set集合变换和下标越界
- map集合
- map集合介绍和常见操作
- map集合常见方法和属性
- map集合变换
- 集合的函数式API
- map函数
- filter函数
- “ all ”“ any ”“ count ”和“ find ”:对集合应用判断式
- 别样的求和方式:sumBy、sum、fold、reduce
- 根据人的性别进行分组:groupBy
- 扁平化——处理嵌套集合:flatMap、flatten
- 惰性集合操作:序列
- 区间、数组、集合之间转换
- 面向对象
- 面向对象-封装
- 类的创建及属性方法访问
- 类属性和字段
- 构造器
- 嵌套类(内部类)
- 枚举类
- 枚举类遍历&枚举常量常用属性
- 数据类
- 密封类
- 印章类(密封类)
- 面向对象-继承
- 类的继承
- 面向对象-多态
- 抽象类
- 接口
- 接口和抽象类的区别
- 面向对象-深入
- 扩展
- 扩展:为别的类添加方法、属性
- Android中的扩展应用
- 优化Snackbar
- 用扩展函数封装Utils
- 解决烦人的findViewById
- 扩展不是万能的
- 调度方式对扩展函数的影响
- 被滥用的扩展函数
- 委托
- 委托类
- 委托属性
- Kotlin5大内置委托
- Kotlin-Object关键字
- 单例模式
- 匿名类对象
- 伴生对象
- 作用域函数
- let函数
- run函数
- with函数
- apply函数
- also函数
- 标准库函数
- takeIf 与 takeUnless
- 第二阶段重点深入
- Lambda编程
- Lambda成员引用高阶函数
- 高阶函数
- 内联函数
- 泛型
- 泛型的分类
- 泛型约束
- 子类和子类型
- 协变与逆变
- 泛型擦除与实化类型
- 泛型类型参数
- 泛型的背后:类型擦除
- Java为什么无法声明一个泛型数组
- 向后兼容的罪
- 类型擦除的矛盾
- 使用内联函数获取泛型
- 打破泛型不变
- 一个支持协变的List
- 一个支持逆变的Comparator
- 协变和逆变
- 第三阶段难点突破
- 注解和反射
- 声明并应用注解
- DSL
- 协程
- 协程简介
- 协程的基本操作
- 协程取消
- 管道
- 慕课霍丙乾协程笔记
- Kotlin与Java互操作
- 在Kotlin中调用Java
- 在Java中调用Kotlin
- Kotlin与Java中的操作对比
- 第四阶段专题练习
- 朱凯Kotlin知识点总结
- Kotlin 基础
- Kotlin 的变量、函数和类型
- Kotlin 里那些「不是那么写的」
- Kotlin 里那些「更方便的」
- Kotlin 进阶
- Kotlin 的泛型
- Kotlin 的高阶函数、匿名函数和 Lambda 表达式
- Kotlin协程
- 初识
- 进阶
- 深入
- Kotlin 扩展
- 会写「18.dp」只是个入门——Kotlin 的扩展函数和扩展属性(Extension Functions / Properties)
- Kotlin实战-开发Android