用C++做資料分析 | CERN ROOT 教學[02] - 資料匯入與簡單分析


用C++做資料分析 | CERN ROOT 教學[02] - 資料匯入與簡單分析

簡介

上一篇文章中介紹了ROOT的基本使用與函數繪製。在這邊文章中筆者會以著名的Iris dataset介紹如何使用ROOT進行資料分析。

資料可以在這裡下載:https://www.kaggle.com/uciml/iris/data

數據分析

把下載回來的資料解壓鎖後會有兩個檔案。Iris.csvdatabase.sqlite。因為csvsqlite常見所以我們先使用csv看看。

root [0] rdf = ROOT::RDF::MakeCsvDataFrame("Iris.csv")
(ROOT::RDataFrame &) A data frame associated to the data source "CSV data source"

ROOT的RDataFrame具同Python裡Pandas提供的DataFrame一樣的功能。他是一個能夠儲存數據的二維表格。只是由於RDataFrame是在去年才正式推出的功能,他的使用上還是有點受限。

我們可以透過GetColumnNames() 得到所有欄位的名稱

root [1] rdf.GetColumnNames()
(ROOT::RDF::RInterface::ColumnNames_t) { "Id", "SepalLengthCm", "SepalWidthCm", "PetalLengthCm", "PetalWidthCm", "Species" }

SepalLengthCm看起來是個有意思的欄位。我們可以使用RDataFrame::Histo1D查看這個欄位的數值分佈。

root [2] h1 = rdf.Histo1D("SepalLengthCm");
root [3] h1->Draw()
SepalLengthCm的Histogram

在這裡使用筆電的讀者如果有跟著操作的話有可能會注意到h1->Draw()的執行速度比前面h1 = rdf.Histo1D("SepalLengthCm")還要慢。這是正常的現象。RDataFrame下幾乎所有的運算都是Lazy Evaulated,也就是說只有當真正需要資料的時候才會去進行計算,前面的步驟都只是在準備而已。

這張圖看起來有些像是常態分佈。為了驗證我們用Fit函數試著將常態分佈擬合到這個圖形上看看。

root [4] h1->Fit("gaus");
 FCN=42.6871 FROM MIGRAD    STATUS=CONVERGED      77 CALLS          78 TOTAL
                     EDM=1.83384e-08    STRATEGY= 1      ERROR MATRIX ACCURATE 
  EXT PARAMETER                                   STEP         FIRST   
  NO.   NAME      VALUE            ERROR          SIZE      DERIVATIVE 
   1  Constant     4.94917e+00   6.56929e-01   1.54143e-03  -2.95222e-04
   2  Mean         5.82870e+00   1.09569e-01   3.41844e-04  -9.68451e-04
   3  Sigma        9.28614e-01   1.19380e-01   1.05036e-04  -1.58562e-03
將高斯分佈擬合的結果

不過一個常態分佈可能沒辦法提供太多有用的資訊。沒關係。我們可以用Filter()過濾某些特定品種的資料。FilterHisto1D一樣屬於 lazey evaulation,只有在必要的時候才會進行計算來降低需要的處理資源。

root [5] h1 = rdf.Filter("Species == \"Iris-setosa\"").Histo1D("SepalLengthCm");
root [6] h1->Draw()
Iris-setosa的SepalLengthCm的分佈

好吧,看起來沒有太多幫助。But you get the idea. Filter能夠根據用來過濾資料。除了生成Histogram外我們也可以用Plot生成Scatter plot. 在這裡就可以看出ROOT已經有些年紀了。不像現代的繪圖程式會用參數決定繪圖的模式,ROOT依靠各種Method與parser決定樣式。詳細的設定方法可以參考ROOT的說明文件

root [7] g1 = rdf.Graph("SepalLengthCm", "PetalLengthCm");
root [8] g1->SetMarkerStyle(6);
root [9] c1->Clear();
root [10] g1->Draw("AP");
用ROOT畫出來的scatter plot

這時如果我們想,也是可以對這張圖進行函數擬合。看起來頗線性的,我們試試看線性函數 pol1。(代表Polynomial 1。同理二次函數則是pol2,以此類推。)

root [11] g1->Fit("pol1")

****************************************
Minimizer is Linear
Chi2                      =      111.365
NDf                       =          148
p0                        =     -7.09519   +/-   0.506447    
p1                        =      1.85748   +/-   0.0858193
使用線性函數擬合至scatter plot上

那這兩筆資料有多相關呢?我們可以透過相關係數得知。

root [12] g1->->GetCorrelationFactor()
(double) 0.87173546

小節

本文展示了ROOT下基本的資料分析方法。能夠載入資料與繪製不同種的圖表。RDataFrame是ROOT新的資料載入界面(相較於行之有年的TTree系統),能簡單的操作資料與繪製圖形。

#C++ #CERN #ROOT #Big Data #AI






留言討論