TL;DR
- 機械学習や統計で基本となるCSVデータの扱い方を書きます。
- Juliaでは、CSVをDataFrameとして扱うことができます。
- RやPythonでCSVを扱ったことがあればすぐに使いこなすことができます。
下準備編
専用パッケージの追加
このコードを実行することでCSVを扱うために必要なパッケージが追加されます。
スクリプトでも実行可能ですが、Repl環境で実行することをおすすめします。
using Pkg
Pkg.add("CSV")
Pkg.add("DataFrames")
パッケージのロード
このコードを実行することでCSVパッケージがロードされます。
初回はビルドが走るので若干時間がかかります。
using CSV
using DataFrames
本編
前提条件
解説のためにこのCSVデータを扱います。タイタニック乗客のデータです。
http://web.stanford.edu/class/archive/cs/cs109/cs109.1166/stuff/titanic.csv
詳細を知りたい方は以下リンクを参照してください。
http://web.stanford.edu/class/archive/cs/cs109/cs109.1166/problem12.html
CSVをデータフレームとしてロードする
CSV.read(ファイルパス, DataFrame)
を使います。
次のコードを実行することで、titanic
にCSVがデータフレームとして代入されます。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame) # ロード
データフレームをCSVとしてセーブする
CSV.write(ファイルパス,dataframe)
を使います。
次のコードを実行することでoutput.csv
という名前でセーブできます。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
CSV.write("./output.csv",titanic) # セーブ
列を指定して配列として取得する
列番号で指定
dataframe[列番号]
で取得できます。
※ Juliaはインデックス番号が1から始まるので注意。
次のコードを実行することで1列目のSurvived
を配列として取得することができる。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
survived = titanic[1]
列名で指定
dataframe.列名
で取得できます。
次のコードを実行することでSex
の列を配列として取得することができる。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
sex = titanic.Sex
dataframe[:列名]
のように書くこともできます。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
sex = titanic[:Sex]
dataframe[Symbol("列名")]
のように書くこともできます。
列名に空白が入っている場合に便利です。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
parentChildren_Aboard = titanic[Symbol("Parents/Children Aboard")]
列を指定して切り抜く・並び替える
dataframe[[:列名1,:列名2,:列名3,...]]
で列の切り抜き・並び替えができます。
次のコードでSex,Name,Age
のデータフレームを作成できます。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
titanic2 = titanic[[:Sex,:Name,:Age]]
行を指定して切り抜く・並び替える
dataframe[[行番号1,行番号2,行番号3,...],:]
で行の切り抜き・並び替えができます。
次のコードで3行目、4行目、8行目を切り抜いたデータフレームを作成できます。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
titanic2 = titanic[[3,4,8],:]
ある行からある行までまとめて切り抜く場合はdataframe[行番号1:行番号2,:]
のように書くこともできます。
次のコードで10行目から20行目までを切り抜いたデータフレームを作成できます。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
titanic2 = titanic[10:20,:]
条件に合う行を切り抜く
dataframe[行数分のtrue/false配列,:]
でtrueの行だけ切り抜きます。
次のコードでSex
がfemale
の行だけ切り抜いたデータフレームを作成できます。
※Juliaでは、f.(array)
のように.
を付けて関数を実行するとmap(f,array)
のように動作します。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
function isFemale(sex)
return sex == "female"
end
female = titanic[isFemale.(titanic.Sex),:]
このケースではもっと簡単に、次のように書くこともできます。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
female = titanic[titanic.Sex .== "female",:]
Age
が20以上の行を切り抜く場合は次のように書きます。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
over20 = titanic[titanic.Age .>= 20,:]
データの書き換え
dataframe[行番号,:列名] = 書き換えたい値
で値を書き換えることができます。
次のコードでは一行目のSex
をboy
に書き換えます。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
titanic[1,:Sex] = "boy"
例えば、Sex
のfemale
をgirl
、male
をboy
に書き換えるには次のように書きます。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
titanic[titanic.Sex .== "male",:Sex] = "boy"
titanic[titanic.Sex .== "female",:Sex] = "girl"
ソート
CSV.sort(dataframe,:列名)
でデータフレームをソートすることができます。
次のコードではAge
を基準にソートします。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
ageSorted = CSV.sort(titanic,:Age)
行数、列数を取得する
size(dataframe)
で取得できます。
列数はsize(dataframe)[1]
、行数はsize(dataframe)[2]
です。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
row = size(titanic)[1]
col = size(titanic)[2]
簡単な情報を表示する
CSV.describe(dataframe)
で各列の中央値、平均値などの簡単な情報を確認できます。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
CSV.describe(titanic)
クロス集計
CSV.by(dataframe,:グルーピングする列名,:列名1 => 関数1,:列名2 => 関数2...)
で行えます。
関数1
にはグループの列名1
から切り出した値の配列を引数として与えられます。
同様に関数2
にはグループの列名2
から切り出した値の配列を引数として与えられます。
例えば、性別による生存者、死者の集計は次のコードで行えます。
using CSV
using DataFrames
titanic = CSV.read("./titanic.csv", DataFrame)
by( titanic,
:Sex, # Sexでグルーピングする
:Survived => sum, # Survivedが1の場合は生存なので、合計すると生存者数になる
:Survived => x -> sum(x.==0) # Survivedが0の場合は死者なので、0の数を合計すると死者数になる
)
結合
vcat(dataframe1,dataframe2)
で縦方向に結合できる。
hcat(dataframe1,dataframe2)
で横方向に結合できる。
最後に
「dplyrないの?」「LINQ使いたい」って方はDataFramesMetaを使うと気持ちよくなれるかもしれません。
https://github.com/JuliaData/DataFramesMeta.jl
これについても書きたかったですが、力尽きました。
「●●が入ってないやん」
「●●が間違ってる」
「●●の方がスマート」
等のマサカリ大歓迎です。
「良かった」
「悪かった」
「タヒね」
等の感想いただけると大変うれしいです。