我用Rust 重写了之前的Pandas 处理时序异常的案例。
关于这个案例的Python版本,可以参考文章:
Python用def 定义函数,Rust 用fn。
Python 文件的后缀是py,Rust文件的后缀是rs。
Python 用_init_来表明模块,Rust 用mod 来声明模块的路径。
Rust 的main 函数是程序的入口点, 所以每个项目都会带有Main函数。
Rust 必须像C语言一样编译成二进制文件,才能运行。但是,比较厉害的是,Rust可以在jupyter notebook里面运行,这就说明Rust 做数据科学指日可待。
Rust 对模块和函数的可见性是强制检测的。通过 `pub` 关键字,我们可以控制模块和函数的可见性。在Python语言中,一个类Class的所有对象都是公共的,如果你想让某些函数私有,可以命名为“_function_name”,但这是“君子协议”,不代表任何约束力。
这段代码的目的是读取 CSV 数据,进行数据处理,然后生成散点图和异常值的可视化。
静态类型:Rust 是静态类型语言,变量的类型在编译时是需要确定的。例如, 可以显式或隐式指定 `data_file_path` 的类型为字符串引用。
所有权:Rust 引入了所有权系统,即每个值都有一个对应的所有者。这可通过 let 关键字将值绑定到变量,所有权的转移由这些 let 语句控制。
可变性:使用 `let mut df` 表示 `df` 是可变的,这是 Rust 中引入了可变性的概念。这符合 Rust 的借用和所有权系统,确保在运行时不存在数据竞争。借用和所有权是Rust在所有编程语言独树一帜的特性,也是让Rust新手最困惑的部分。
模块间引用:使用 `use statistics::IS_NORMALY_COL;` 引入了一个常量,显示了模块间的引用关系,以及 Rust 的模块系统如何支持可见性和封装性。
函数调用与借用:Rust 函数的调用通常会涉及DataFrame所有权转移,所以使用 `clone()` 来创建数据的副本,相当于借用,而不是转移所有权。另外需要强调的是这里的clone 其实就是clone 指针,而不是真的deepclone。这是Polars包的一个设计优势。
末尾分号和花括号:Rust 要求在语句的末尾加上分号,以表示语句的结束。这是 Rust 语法的一部分,与 Python 不同,这有助于显式地分隔语句。花括号表明一段生命周期,如果没有转移所有权,当程序运行到花括号外面时,所有的数据自动从内存清除。
错误处理:在这段代码中,使用了 `unwrap()` 来获取 `Result` 类型的值。在实际生产代码中,可能需要更健壮的错误处理方式,例如使用 `match` 或 `?` 运算符。但是这里看到Rust 强调程序的健壮性,已经设计好很多帮你发现错误或者防呆的机制。
我们再来看一下数据处理和分析部分,这部分我们采用的Polars 包。我称之为包,是因为Python出身,专业点还是叫crate。
可能较大的差异是,Rust里面你要经常考虑Option和Result的unwrap。
又到了我最爱的Plotly。没错,Rust也是支持Plotly的,而且体验感也不错。
对于我们之前写的Python代码,几乎可以拿来使用。
和数据处理相同的注意事项是,我们需要不断的unwrap结果,以及需要确保数据格式是完全匹配的。
我们可以看到熟悉的Plotly画面了。
约10年前,我刚从当当买了一本C++机器视觉,想精湛一下C++技术。
回家时遇到了朋友,他神神叨叨的告诉我:你学啥C++,学蟒蛇啊。
我并没有放在心上。
大约5年前,我开始学习蟒蛇Python了。
每每想起来,我觉得自己的确是那个只会低头走路,不愿抬头看方向的人。
所以,2023年末,如果你要问我学啥,我会说:学啥Python啊,学螃蟹啊。
微信扫一扫
关注该公众号