昨日は、ヒストグラムを出力するところまでで終わってしまった。いつまでヒストグラムやってるんだって感じなので早く先に行きたい

ヒストグラム描くサンプルコードをDataFrame用に改変する

ヒストグラムを描くサンプルコードは次のような感じだった

use plotters::prelude::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let root = BitMapBackend::new("histogram.png", (640, 480)).into_drawing_area();

    root.fill(&WHITE)?;

    let mut chart = ChartBuilder::on(&root)
        .x_label_area_size(35)
        .y_label_area_size(40)
        .margin(5)
        .caption("Histogram Test", ("sans-serif", 50))
        .build_cartesian_2d((0u32..10u32).into_segmented(), 0u32..10u32)?;

    chart
        .configure_mesh()
        .disable_x_mesh()
        .bold_line_style(&WHITE.mix(0.3))
        .y_desc("Count")
        .x_desc("Bucked")
        .axis_desc_style(("sans-serif", 15))
        .draw()?;

    let data = [
        0u32, 1, 1, 1, 4, 2, 5, 7, 8, 6, 4, 2, 1, 8, 3, 3, 3, 4, 4, 3, 3, 3,
    ];

    chart.draw_series(
        Histogram::vertical(&chart)
            .style(RED.mix(0.5).filled())
            .data(data.iter().map(|x: &u32| (*x, 1))),
    )?;

    Ok(())
}

これをDataFrameを受け取るようにし、その中で"lidar"というカラムに対して描画をするように変えたい、というのが今回考えていることだ。まず次のような感じにしてみた。変更点は、build_cartesian_2dの中で横軸をデータに合わせて範囲指定するようにしたことと、データをDataFrameに格納されているものを使うようにしたことぐらいだ。

fn draw_histogram(df: DataFrame) -> Result<(), Box<dyn std::error::Error>> {
    let root = BitMapBackend::new("lidar_200_histogram.png", (640, 480)).into_drawing_area();

    root.fill(&WHITE)?;

    let lidar = df.column("lidar").expect("could not find `lidar` column");
    let lidar_max = lidar.max().expect("cannot take max operation") as u32;
    let lidar_min = lidar.min().expect("cannot take min operation") as u32;

    let mut chart = ChartBuilder::on(&root)
        .x_label_area_size(35)
        .y_label_area_size(40)
        .margin(5)
        .caption("Lidar Histogram", ("sans-serif", 30))
        .build_cartesian_2d((lidar_min..lidar_max).into_segmented(), 0u32..5000u32)?;

    chart
        .configure_mesh()
        .bold_line_style(&WHITE.mix(0.3))
        .y_desc("Count")
        .x_desc("Lidar")
        .axis_desc_style(("sans-serif", 15))
        .draw()?;

    chart
        .draw_series(
            Histogram::vertical(&chart)
                .style(BLUE.mix(0.5).filled())
                .data(lidar.into_iter().map(|x: &i64| (*x, 1))),
        )?;

    Ok(df)
}

しかしこれでは次のようなエラーが出てしまう

--> src/main.rs:39:48
   |
39 | fn draw_histogram(df: DataFrame) -> Result<(), Box<dyn std::error::Error>> {
   |                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^ unexpected type argument

error: aborting due to previous error

For more information about this error, try `rustc --explain E0107`.
error: could not compile `lidar_200`

そもそもResultとは?Boxとは?dynとは?という感じなのでどう直せばいいかわからない。とりあえず調べてみよう。以下、E0107の内容だが・・・うん、意味わからん

Resultに与えられるパラメータ?が多すぎるという意味だろうか?しかしこれは前のヒストグラムのサンプルコードの時はバッチリ動いていたんだが・・・。

とりあえずResultが怪しいので調べてみた。

The Rust Programming Language 日本語版

うーむ、わからん・・・どうやら、関数内で?を使うとその式の結果がエラーになった場合はそこで終了してエラーを返してくれる、そうでなければその式を評価した結果が返される、というようになっているらしい。確かに関数内では何箇所か?使っている。しかし、これがどうunexpected type argumentに繋がるのかかけらもわからん。

よくわからないので、とりあえず?をやめて全部.expect()に変えた上で関数の返り値をResult<DataFrame>に変えてみたらよくわからないエラーは全部消えて