CERN ROOT (C++) グラフ作成 (5) CSVファイルデータから簡単に散布図を描く -- ４選

# 概要
C++でもCSVファイルのデータ入力して数行のコードで簡易なグラフを作成することができます。CSVファイルから散布図を描く４通りのやり方を紹介したいと思います。今回はREPL上だけで行います。

# 実行環境
```zsh
sw_vers
ProductName:		macOS
ProductVersion:		14.6.1
BuildVersion:		23G93

root --version
ROOT Version: 6.32.06
Built for macosxarm64 on Sep 21 2024, 18:21:53
From tags/6-32-06@6-32-06
```

# 散布図用のデータ
カンマ区切りのデータ3x50個の乱数で作成したデータを用意しました。

```testdata.txt
0.154300,0.423245,0.790600
0.246387,0.193708,0.169346
0.775951,0.217542,0.861995
0.599383,0.490301,0.894267
0.383607,0.993726,0.777661
0.044493,0.850140,0.390310
0.028817,0.054248,0.854496
0.520053,0.705135,0.334760
0.927768,0.240329,0.149474
0.024483,0.122621,0.935241
0.777959,0.204795,0.586894
0.851431,0.246359,0.348120
0.471198,0.838196,0.684834
0.217217,0.014237,0.460644
0.594782,0.934396,0.149627
0.954652,0.501548,0.439404
0.477935,0.992369,0.956747
0.054731,0.947715,0.727018
0.983940,0.377090,0.089267
0.085735,0.561423,0.213820
0.144892,0.779222,0.235873
0.782956,0.939370,0.996931
0.460609,0.895729,0.834432
0.256555,0.752201,0.340227
0.610958,0.376559,0.259205
0.184988,0.622668,0.040514
0.836739,0.221261,0.065041
0.921972,0.220682,0.262685
0.703217,0.838644,0.395228
0.521148,0.902643,0.904619
0.747547,0.777559,0.306192
0.149385,0.103309,0.566300
0.001523,0.572392,0.236814
0.092093,0.522424,0.101915
0.949487,0.098046,0.527890
0.426964,0.310475,0.403611
0.502683,0.170991,0.153106
0.331226,0.323127,0.376139
0.420963,0.740368,0.031891
0.766797,0.457309,0.887784
0.665503,0.761191,0.831626
0.832645,0.478346,0.699783
0.797013,0.605364,0.406897
0.259209,0.972193,0.858845
0.117939,0.520514,0.341878
0.220899,0.484517,0.660442
0.169245,0.066583,0.833371
0.734511,0.914272,0.929211
0.807613,0.520643,0.751681
0.268784,0.188375,0.892091
```

# 1. TGraphで直接ファイルを指定

```
root [0] auto gr = new TGraph("testdata.txt","%lg,%lg");
root [1] gr->SetMarkerStyle(20);
root [2] gr->Draw("ap");
Info in <TCanvas::MakeDefCanvas>:  created default TCanvas with name c1
root [3]
```

![2024-10-29 22.20.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258007/e40e4bb3-9635-9532-c631-b2b3726476eb.png)



`TGraph`第２引数は`scanf`と同じように指定します。上記に例ではデータの第1,2列を使ってグラフを作成しています。第1,3列を使う場合は次のように使わない第2列に`*`指定します。

```
"%lg,%*lg,%lg"
```


# 2. TNtupleを使う

```
root [0] auto gr = new TNtuple("test","data for Graph","x:y:z");
root [1] gr->ReadFile("testdata.txt", "test data", ',');
root [2] gr->SetMarkerStyle(20);
root [3] gr->Draw("x:y");
Info in <TCanvas::MakeDefCanvas>:  created default TCanvas with name c1
root [4]
```


![2024-10-29 22.29.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258007/47426b8a-eff4-a6ee-8d4a-d3541795c7c7.png)

:::note warn
注意
`Draw`の引数は"x:y"ですが、グラフは`y-x`になっているので注意してください。つまり`x-y`にしたいときは`Draw("y:x")`にすること。
:::

`TNtuple`の第３引数は各列にx,y,zという名前をつけるため指定します。`ReadFile`の第３引数はCSVファイルのデータのデリミタを指定します。タイプがcharなのでシングルクォーテーションで囲ってください。`TNtuple`の注意点としてはデータのタイプが**float**のみのようです。


# 3. RDataFrameを使う

```
root [0] auto df = ROOT::RDF::FromCSV("testdata.txt",false,',');
root [1] auto gr = df.Graph("Col0","Col1");
root [2] gr->SetMarkerStyle(20);
root [3] gr->Draw("ap");
Info in <TCanvas::MakeDefCanvas>:  created default TCanvas with name c1
root [4]
```
![2024-10-29 22.33.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258007/8d30dc66-ac37-f07a-1354-dbe1bba0edef.png)

`df`はポインタでないことに注意してください。
`FromCSV`の第２引数は列名を示す先頭行の有無を指定しますが、今回は無いので**false**です。第３引数はデリミタです。列名が無いときは**Col0**,**Col1**のような列名が自動的につけられます。列名を確認していときは以下の命令を実行します。
```
root [6] df.GetColumnNames()
ROOT::RDF::ColumnNames_t) { "Col0", "Col1", "Col2" }
root [7]
```
()のあとに;を付けいないとコンソール上に表示されます。

# 4. TTreeを使う

```
root [0] auto tree = new TTree("tree","test", 3);
root [1] tree->ReadFile("testdata.txt", "x/F:y/F:z/F", ',');
root [2] tree->SetMarkerStyle(20);
root [3] tree->Draw("x:y");
Info in <TCanvas::MakeDefCanvas>:  created default TCanvas with name c1
root [4]
```

![2024-11-13 18.51.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258007/032b2b72-5537-995d-08a8-2a2592089146.png)

:::note warn
注意
`Draw`の引数は"x:y"ですが、グラフは`y-x`になっているので注意してください。つまり`x-y`にしたいときは`Draw("y:x")`にすること。
:::

`TTree`の第３引数はCSVファイルのデータの列数が4以上だと省略できるようですが、3以下だと列数以下の値を指定すれば大丈夫のようです。これは`splitlevel`というようですが、いまいち分かりませんでした。
`ReadFile`の第２引数は**列名/データタイプ**を`:`を区切り文字として列数分指定います。列名だけだと**F**つまりfloatが既定値のようです。その他には**D**はdouble、**I**はinteger、**L**はlong long、**C**はstringなどです。
CSVファイルの先頭行に列名情報があれば第２引数は空文字でも良いようです。

# 終わりに
簡単にグラフを表示するという観点で調べて紹介したのが上記の４つです。読み取ったデータは単にデータとしても活用出来るようです。