一、业务内容
- 读入csv文件到dataframe里
- 生成新的列【“MA5"】
- 计算MA5指标
- 把dataframe重新保存成csv文件
二、涉及的rust知识
- ploars包(用于dataframe的处理)的简单使用
- dataframe增加列的操作
- dataframe的打印
- 自定义函数
- 闭包的使用
- 读取csv到df中
- 把df保存到csv中
- map的使用
- series的切片
- 条件表达式的使用
三、具体实现
1、待处理的csv文件——某只k线文件
2、包的引用
主要用到的是polars,这个包等同于python中的pandas以及julia中的dataframes。
参观和学习的地址:
官网地址:https://docs.rs/polars/latest/polars/
仓库地址:https://github.com/pola-rs/polars
extern crate polars;
use polars::prelude::*;
use std::fs::File;
3、生成一个dataframe
DataFrame::default()
let mut df = DataFrame::default();
4、df里面增加一列
df.with_column()
df.with_column(Series::new("榜号",vec![1,2,3]));
df.with_column(Series::new("姓名",vec!["张三丰","黄老邪","老顽童"]));
5、 生成一个series
Series::new()
let mySeries = Series::new("姓名",vec!["张三丰","黄老邪","老顽童"]);
6、读取csv到df 中
CsvReader::new()
/// 功能:读取csv文件,转成dataframe
/// 输入:filePath:String ,文件路径和名字
/// 输出:Result<DataFrame>
///
/// # Examples
/// ```
/// use polars::prelude::*;
/// use std::fs::File;
/// let df = read_csv("D:/csvTest/000004.csv".to_string());
/// println!("{:?}", df);
/// ```
///
fn read_csv(filePath: String) -> Result<DataFrame>
{
let file = File::open(filePath).expect("找不到文件");
CsvReader::new(file)
.infer_schema(None)
.has_header(true)
.finish()
}
测试代码:
use polars::prelude::*;
use std::fs::File;
let df = read_csv("D:/csvTest/000004.csv".to_string());
println!("{:?}", df);
7、把df保存成csv文件
write_csv::new()
/// 【功能】把dataframe保存成csv
/// 输入:
/// df: &mut DataFrame
/// filePath:String
/// 输出:Result<()>
///
/// # Examples
/// ```
/// extern crate polars;
/// use polars::prelude::*;
/// let mut df = DataFrame::default();
/// df.with_column(Series::new("榜号",vec![1,2,3]));
/// df.with_column(Series::new("姓名",vec!["张三丰","黄老邪","老顽童"]));
/// write_csv(& mut df,"e:/bbb.csv".to_string());
/// ```
///
fn write_csv(df: &mut DataFrame,filePath:String) -> Result<()> {
let mut file = File::create(filePath).expect("创建文件失败");
CsvWriter::new(&mut file)
.has_header(true) //.has_headers(true)
.with_delimiter(b',')
.finish(df)
}
测试代码:
extern crate polars;
use polars::prelude::*;
let mut df = DataFrame::default();
df.with_column(Series::new("榜号",vec![1,2,3]));
df.with_column(Series::new("姓名",vec!["张三丰","黄老邪","老顽童"]));
write_csv(& mut df,"e:/bbb.csv".to_string());
8、Series如何切片?
mySeries.slice()
let s = Series::new("x", vec!(1,2,3,4,5,6));
let mySliceMean = s.slice(0,3).mean(); //从index为0的item开始取数据,取3个item
println!("{:?}",mySliceMean);
9、map的使用
-
涵义
map,apply以及C#中的select,他们其实是玩法相同。
[1,2,3,4] × 2 = [2,4,6,8]
对系列中的每个item都执行一次相同的处理,处理结果重新生成一个新的系列 -
举例
(1)julia
f(x)=2x
[1,2,3,4] .|> f
结果
[2,4,6,8]
(2)C#
[1,2,3,4] .select(x=>2*x)
结果
[2,4,6,8]
(3)Rust
let q:Series = (0..100).map(|x|(2 * x) as i32).collect();
println!("{:?}", q);
[0,2,4,6,8,.......198]
夫人看了我写的代码,说了句:茴香豆的茴字都写出花来了,有意思吗?
10、闭包的使用
- 话说什么是闭包?
函数、匿名函数、委托、兰姆达、闭包,看见这些词,是不是有想吐的感觉——想吐就对了,我就经常吐。
对于大多数人而言,上古时代的编程语言多半是过程式,比如C.其它古早的函数式语言另论。
我们定义的变量一般都是用来存储数据的。加入有人提出:我有一个函数,我要把它存在一个变量里?
怎么弄,用一种特殊的变量,用来保存该函数的地址,这就是函数指针。
要调用一个函数,你的先定义一个有名有姓(函数签名)的函数,这是传统做法(明媒正娶,昭告乡间)。
后来有人说,我不想提前写那么多琐碎的小函数,我用的时候在定义,于是出现了现写现用的函数,在同一个代码块里面,写好一个临时的函数,然后接着就调用它,这个临时的函数就是匿名函数、表达式。(有点像童养媳了)。
后来有人说,我要在调用的时候直接写,于是你把函数逻辑直接写在一大条语句里,写完即代表调用结束,该求值的也求了,这就是闭包。(我也不知道怎么形容了)
- rust中使用闭包
写在一行里面的闭包
let q:Series = (0..100).map(|x|(2 * x) as i32).collect();
println!("{:?}", q);
如果你的逻辑比较复杂,需要多行处理,那就写多行呗,如下所示,你还能写return!
let q:Series = (0..100).map(
|x|
{
let y = 2*x;
return 2 * y;
}
as i32).collect(); //.collect::<i32<>>()
println!("{:?}", q);
11、k线MA的计算函数
ma是啥,计算公式是啥,去查通*达&信软件,此地不敢多说,免得被封,直接上菜
///【功能】给定一个价格系列,计算周期为n的移动平均MA
fn Ma(prices:&Series,n:usize)->Vec<f32>
{
(0..prices.len()).map(
|x|-> f32
{
let m2 = if(x< n){
NAN
}
else{
prices.slice((x-n) as i64, n).mean().unwrap() as f32
};
return m2;
}
).collect::<Vec<f32>>()
}
收尾:附上一个测试代码,没时间整理,随便看吧,我出门买菜去了
extern crate polars;
//use polars::export::num::ToPrimitive;
// #[cfg(feature = "rolling_window")]
use polars::prelude::*;
use polars::df;
use std::f32::NAN;
use std::fs::File;
use std::collections::HashMap;
//use std::iter::zip;
fn main1() {
println!("Hello, world!!!!!!");
println!("who are you?");
println!("Hello world");
println!("Hello error2");
format!("Hello {}", "world111111");
let df = df!["字母" => ["a", "b", "c", "d"],"数字" => [1, 2, 3, 4]];
println!("{:?}",df);
}
fn main2()
{
let x = std::f64::consts::PI;
let r = 8.0;
println!("计算出来的面积为: {}", x * r * r);
}
/// 功能:读取csv文件,转成dataframe
/// 输入:filePath:String ,文件路径和名字
/// 输出:Result<DataFrame>
///
/// # Examples
/// ```
/// use polars::prelude::*;
/// use std::fs::File;
/// let df = read_csv("D:/csvTest/000004.csv".to_string());
/// println!("{:?}", df);
/// ```
///
fn read_csv(filePath: String) -> Result<DataFrame>
{
let file = File::open(filePath).expect("找不到文件");
CsvReader::new(file)
.infer_schema(None)
.has_header(true)
.finish()
}
/// 【功能】把dataframe保存成csv
/// 输入:
/// df: &mut DataFrame
/// filePath:String
/// 输出:Result<()>
///
/// # Examples
/// ```
/// extern crate polars;
/// use polars::prelude::*;
/// let mut df = DataFrame::default();
/// df.with_column(Series::new("榜号",vec![1,2,3]));
/// df.with_column(Series::new("姓名",vec!["张三丰","黄老邪","老顽童"]));
/// write_csv(& mut df,"e:/bbb.csv".to_string());
/// ```
///
fn write_csv(df: &mut DataFrame,filePath:String) -> Result<()> {
let mut file = File::create(filePath).expect("创建文件失败");
CsvWriter::new(&mut file)
.has_header(true) //.has_headers(true)
.with_delimiter(b',')
.finish(df)
}
fn read_csv_test()
{
let df = read_csv("D:/csvTest/000004.csv".to_string());
println!("{:?}", df);
}
fn main3()
{
//main1();
//main2();
//read_csv_test()
// use iterators
let ca: UInt32Chunked = (0..10).map(Some).collect();
println!("{:?}", ca);
// from slices
let ca = UInt32Chunked::new("foo", &[1, 2, 3]);
println!("{:?}", ca);
// use builders
let mut builder = PrimitiveChunkedBuilder::<UInt32Type>::new("foo", 10);
println!("-----------------------开始打印item------------------------");
for value in 0..10 {
println!("{}",value);
builder.append_value(value);
}
println!("------------------------结束打印item-------------------------");
let ca = builder.finish();
println!("{:?}", ca);
}
fn main_dict()
{
let mut hd: HashMap<&str,DataFrame> = HashMap::new();
let df = read_csv("D:/csvTest/000004.csv".to_string()).unwrap();
hd.insert(&"df", df);
println!("------------------------12131321321321321-------------------------");
println!("{:?}", hd["df"]);
let k = &"df";
hd.remove(k);
println!("{}",hd.len());
}
fn main5()
{
let mut df = read_csv("D:/csvTest/000004.csv".to_string()).unwrap();
println!("{:?}", df);
let ma5 = Series::new("ma5",&df["close"] + &df["open"]);
println!("{:?}", ma5);
df.with_column(ma5); //df增加一列
println!("{:?}", df);
let x = df.column("open").unwrap();
println!("{:?}",x);
let y = &df["close"];
println!("{:?}",y);
println!("{:?}",y);
}
fn main6(){
let arr = [100,200,300,400,500,600];
let mut i=0;
let a=&arr[1..=3];
let len=a.len();
println!("Elements of 'a' array:");
while i<len
{
println!("{}",a[i]);
i=i+1;
}
let mut df = read_csv("D:/csvTest/000004.csv".to_string()).unwrap();
println!("{:?}", df);
let x = df.column("open").unwrap();
println!("{:?}",x);
}
///【功能】给定一个价格系列,计算周期为n的移动平均MA
fn Ma(prices:&Series,n:usize)->Vec<f32>
{
(0..prices.len()).map(
|x|-> f32
{
let m2 = if(x< n){
NAN
}
else{
prices.slice((x-n) as i64, n).mean().unwrap() as f32
};
return m2;
}
).collect::<Vec<f32>>()
}
fn main(){
let s = Series::new("x", vec!(1,2,3,4,5,6));
let mySliceMean = s.slice(0,3).mean();
println!("{:?}",mySliceMean);
let mut df = read_csv("D:/csvTest/000004.csv".to_string()).unwrap();
println!("{:?}", df);
let ma5 = Series::new("ma5",&df["close"]);
println!("{:?}", ma5);
let myMean = ma5.slice(0, 5).mean();
println!("{:?}", ma5);
let a = &df["close"];
let v6 = Ma(&df["close"], 6);
println!("{:?}", v6);
let ma6= Series::new("ma6",v6);
df.with_column(ma6); //df增加一列
println!("{:?}", df);
write_csv(& mut df,"e:/aaa.csv".to_string());
let mut df = DataFrame::default();
df.with_column(Series::new("榜号",vec![1,2,3]));
df.with_column(Series::new("姓名",vec!["张三丰","黄老邪","老顽童"]));
write_csv(& mut df,"e:/bbb.csv".to_string());
let q:Series = (0..100).map(|x|(2 * x) as i32).collect(); //.collect::<i32<>>()
println!("{:?}", q);
let q:Series = (0..100).map(
|x|
{
let y = 2*x;
return 2 * y;
}
as i32).collect(); //.collect::<i32<>>()
println!("{:?}", q);
}