36
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

最近流行りつつある科学計算処理向けの高水準言語「Julia」の基本操作をまとめていきます。
1.準備編
2.確率分布・仮説検定と可視化編
3.データフレーム操作編

chapter.5 データフレーム操作

DataFrames.jl を使ったデータフレーム操作についてまとめます
公式:https://juliadata.github.io/DataFrames.jl/stable/man/getting_started/

1.パッケージ install

julia> import Pkg; Pkg.add("DataFrames")

2.データフレーム生成方法

行列データから生成する場合

julia> data = [
        1  0.179324    "A";
        2  0.818923    "B";
        3  0.979487    "C";
        4  0.882494    "A";
        5  0.00530208  "B"];

julia> DataFrame(data)
5×3 DataFrame
│ Row │ x1  │ x2         │ x3  │
│     │ Any │ Any        │ Any │
├─────┼─────┼────────────┼─────┤
│ 1   │ 1   │ 0.179324   │ A   │
│ 2   │ 2   │ 0.818923   │ B   │
│ 3   │ 3   │ 0.979487   │ C   │
│ 4   │ 4   │ 0.882494   │ A   │
│ 5   │ 5   │ 0.00530208 │ B   │

列名を与える場合

julia> DataFrame(data, [:A, :B, :C])
5×3 DataFrame
│ Row │ A   │ B          │ C   │
│     │ Any │ Any        │ Any │
├─────┼─────┼────────────┼─────┤
│ 1   │ 1   │ 0.179324   │ A   │
│ 2   │ 2   │ 0.818923   │ B   │
│ 3   │ 3   │ 0.979487   │ C   │
│ 4   │ 4   │ 0.882494   │ A   │
│ 5   │ 5   │ 0.00530208 │ B   │

列ベクトルから生成する場合

julia> DataFrame(
           A=1:5,
           B=rand(5),
           C=["A", "B", "C", "A", "B"])
5×3 DataFrame
│ Row │ A     │ B         │ C      │
│     │ Int64 │ Float64   │ String │
├─────┼───────┼───────────┼────────┤
│ 1   │ 1     │ 0.0974522 │ A      │
│ 2   │ 2     │ 0.194185  │ B      │
│ 3   │ 3     │ 0.280582  │ C      │
│ 4   │ 4     │ 0.838387  │ A      │
│ 5   │ 5     │ 0.745305  │ B      │

辞書型データから生成する場合
※以後このデータを使います

julia> data = Dict(
           :A => 1:5,
           :B => rand(5),
           :C => ["A", "B", "C", "A", "B"]);
julia> df = DataFrame(data)
5×3 DataFrame
│ Row │ A     │ B        │ C      │
│     │ Int64 │ Float64  │ String │
├─────┼───────┼──────────┼────────┤
│ 1   │ 1     │ 0.558038 │ A      │
│ 2   │ 2     │ 0.319128 │ B      │
│ 3   │ 3     │ 0.858239 │ C      │
│ 4   │ 4     │ 0.578579 │ A      │
│ 5   │ 5     │ 0.142839 │ B      │

※symbol 型について補足

:A といった表記は symbol 型のデータを表しています。
筆者も詳しくありませんが、変数を表すためのデータと表現すると感覚的に近い気がしています。

julia> string = "A";
julia> typeof(string)
String

julia> symbol = :A;
julia> typeof(symbol)
Symbol

julia> Symbol(string) # String から Symbol への変換
:A

CSV から読み込む場合パッケージが必要


julia> import Pkg; Pkg.add("CSV")
julia> using CSV

手元にデータがないのでとりあえず書き込みから

julia> data = Dict(
           :A => 1:5,
           :B => rand(5),
           :C => ["A", "B", "C", "A", "B"]);
julia> df = DataFrame(data);
julia> CSV.write("dataframe.csv", df)
"dataframe.csv"

読み込み

julia> new_df = CSV.read("dataframe.csv");
julia> new_df
5×3 DataFrame
│ Row │ A     │ B         │ C      │
│     │ Int64 │ Float64   │ String │
├─────┼───────┼───────────┼────────┤
│ 1   │ 1     │ 0.0387064 │ A      │
│ 2   │ 2     │ 0.0974289 │ B      │
│ 3   │ 3     │ 0.281637  │ C      │
│ 4   │ 4     │ 0.566432  │ A      │
│ 5   │ 5     │ 0.685344  │ B      │

3.データ基本情報の確認

先頭 n 行を確認

julia> n = 3;
julia> first(df, n)
3×3 DataFrame
│ Row │ A     │ B        │ C      │
│     │ Int64 │ Float64  │ String │
├─────┼───────┼──────────┼────────┤
│ 1   │ 1     │ 0.558038 │ A      │
│ 2   │ 2     │ 0.319128 │ B      │
│ 3   │ 3     │ 0.858239 │ C      │

最終 n 行を確認

julia> n = 3;
julia> last(df, n)
3×3 DataFrame
│ Row │ A     │ B        │ C      │
│     │ Int64 │ Float64  │ String │
├─────┼───────┼──────────┼────────┤
│ 1   │ 3     │ 0.858239 │ C      │
│ 2   │ 4     │ 0.578579 │ A      │
│ 3   │ 5     │ 0.142839 │ B      │

行数と列数の確認

julia> size(df)
(5, 3)

カラム名を確認

julia> names(df)
3-element Array{Symbol,1}:
 :A
 :B
 :C

データ型を確認

julia> eltype.(eachcol(df))
3-element Array{DataType,1}:
 Int64  
 Float64
 String 

各種統計量(など)を確認

julia> describe(df)
3×8 DataFrame. Omitted printing of 2 columns
│ Row │ variable │ mean     │ min      │ median   │ max      │ nunique │
│     │ Symbol   │ Union…   │ Any      │ Union…   │ Any      │ Union…  │
├─────┼──────────┼──────────┼──────────┼──────────┼──────────┼─────────┤
│ 1   │ A        │ 3.0      │ 1        │ 3.0      │ 5        │         │
│ 2   │ B        │ 0.491365 │ 0.142839 │ 0.558038 │ 0.858239 │         │
│ 3   │ C        │          │ A        │          │ C        │ 3       │

4.データ抽出

R, numpy, pandas とほぼ同じ書き方です

列を取り出す

julia> df.A
5-element Array{Int64,1}:
 1
 2
 3
 4
 5

複数列を取り出す

julia> df[:,[:A, :B]]
5×2 DataFrame
│ Row │ A     │ B        │
│     │ Int64 │ Float64  │
├─────┼───────┼──────────┤
│ 1   │ 1     │ 0.558038 │
│ 2   │ 2     │ 0.319128 │
│ 3   │ 3     │ 0.858239 │
│ 4   │ 4     │ 0.578579 │
│ 5   │ 5     │ 0.142839 │

列を取り出して算術も簡単


julia> df.D = df.A .* 40;
julia> df
5×4 DataFrame
│ Row │ A     │ B        │ C      │ D     │
│     │ Int64 │ Float64  │ String │ Int64 │
├─────┼───────┼──────────┼────────┼───────┤
│ 1   │ 1     │ 0.558038 │ A      │ 40    │
│ 2   │ 2     │ 0.319128 │ B      │ 80    │
│ 3   │ 3     │ 0.858239 │ C      │ 120   │
│ 4   │ 4     │ 0.578579 │ A      │ 160   │
│ 5   │ 5     │ 0.142839 │ B      │ 200   │

行を抽出

julia> df[2, :]
DataFrameRow
│ Row │ A     │ B        │ C      │ D     │
│     │ Int64 │ Float64  │ String │ Int64 │
├─────┼───────┼──────────┼────────┼───────┤
│ 2   │ 2     │ 0.319128 │ B      │ 80    │

複数行を抽出


julia> df[2:5,:] # row index が変わっている点に注意!
4×4 DataFrame
│ Row │ A     │ B        │ C      │ D     │
│     │ Int64 │ Float64  │ String │ Int64 │
├─────┼───────┼──────────┼────────┼───────┤
│ 1   │ 2     │ 0.319128 │ B      │ 80    │
│ 2   │ 3     │ 0.858239 │ C      │ 120   │
│ 3   │ 4     │ 0.578579 │ A      │ 160   │
│ 4   │ 5     │ 0.142839 │ B      │ 200   │

条件抽出

julia> df[df.A.>3,:]
2×4 DataFrame
│ Row │ A     │ B        │ C      │ D     │
│     │ Int64 │ Float64  │ String │ Int64 │
├─────┼───────┼──────────┼────────┼───────┤
│ 1   │ 4     │ 0.578579 │ A      │ 160   │
│ 2   │ 5     │ 0.142839 │ B      │ 200   │

複数条件による抽出

julia> df[(df.A.>3).&(df.C.=="B"),:]
1×4 DataFrame
│ Row │ A     │ B        │ C      │ D     │
│     │ Int64 │ Float64  │ String │ Int64 │
├─────┼───────┼──────────┼────────┼───────┤
│ 1   │ 5     │ 0.142839 │ B      │ 200   │

抽出した条件の値を書き換える

julia> df[(df.A.>3).&(df.C.=="B"),:C] .= "X";
julia> df
5×4 DataFrame
│ Row │ A     │ B        │ C      │ D     │
│     │ Int64 │ Float64  │ String │ Int64 │
├─────┼───────┼──────────┼────────┼───────┤
│ 1   │ 1     │ 0.558038 │ A      │ 40    │
│ 2   │ 2     │ 0.319128 │ B      │ 80    │
│ 3   │ 3     │ 0.858239 │ C      │ 120   │
│ 4   │ 4     │ 0.578579 │ A      │ 160   │
│ 5   │ 5     │ 0.142839 │ X      │ 200   │

5.結合(join, append)

Union

julia> df2 = DataFrame(
            A=[10],
            B=[0.1],
            C=["C"],
            D=[20]);
julia> append!(df, df2) # 再帰的なので注意!
6×4 DataFrame
│ Row │ A     │ B        │ C      │ D     │
│     │ Int64 │ Float64  │ String │ Int64 │
├─────┼───────┼──────────┼────────┼───────┤
│ 1   │ 1     │ 0.558038 │ A      │ 40    │
│ 2   │ 2     │ 0.319128 │ B      │ 80    │
│ 3   │ 3     │ 0.858239 │ C      │ 120   │
│ 4   │ 4     │ 0.578579 │ A      │ 160   │
│ 5   │ 5     │ 0.142839 │ X      │ 200   │
│ 6   │ 10    │ 0.1      │ C      │ 20    │

Join
デフォルトでは inner join

julia> df3 = DataFrame(C = ["A", "B"],E=["abc", "xyz"]);
julia> join(df, df3, on=:C)
3×5 DataFrame
│ Row │ A     │ B        │ C      │ D     │ E      │
│     │ Int64 │ Float64  │ String │ Int64 │ String │
├─────┼───────┼──────────┼────────┼───────┼────────┤
│ 1   │ 1     │ 0.558038 │ A      │ 40    │ abc    │
│ 2   │ 2     │ 0.319128 │ B      │ 80    │ xyz    │
│ 3   │ 4     │ 0.578579 │ A      │ 160   │ abc    │

left join

julia> join(df, df3, on=:C, kind=:left)
6×5 DataFrame
│ Row │ A     │ B        │ C      │ D     │ E       │
│     │ Int64 │ Float64  │ String │ Int64 │ String⍰ │
├─────┼───────┼──────────┼────────┼───────┼─────────┤
│ 1   │ 1     │ 0.558038 │ A      │ 40    │ abc     │
│ 2   │ 2     │ 0.319128 │ B      │ 80    │ xyz     │
│ 3   │ 3     │ 0.858239 │ C      │ 120   │ missing │
│ 4   │ 4     │ 0.578579 │ A      │ 160   │ abc     │
│ 5   │ 5     │ 0.142839 │ X      │ 200   │ missing │
│ 6   │ 10    │ 0.1      │ C      │ 20    │ missing │
#  なぜか文字化けが起こる...

詳細はこちら

6.集計(aggregate, by)

aggregate 関数
・第一引数にdataframe
・第二引数に集計 key とするカラム名(配列にすると multi index 集計)
・第三引数に集計方法(配列可)

julia> aggregate(df, :C, sum) 
4×4 DataFrame
│ Row │ C      │ A_sum │ B_sum    │ D_sum │
│     │ String │ Int64 │ Float64  │ Int64 │
├─────┼────────┼───────┼──────────┼───────┤
│ 1   │ A      │ 5     │ 1.13662  │ 200   │
│ 2   │ B      │ 2     │ 0.319128 │ 80    │
│ 3   │ C      │ 13    │ 0.958239 │ 140   │
│ 4   │ X      │ 5     │ 0.142839 │ 200   │

※集計を行う場合は Statistics.jl を入れておいたほうがいい。

julia> import Pkg; Pkg.add("Statistics")
julia> using Statistics

なぜかmeanも無い( describe では mean あったのに何故!?)

by 関数
・第一引数にdataframe
・第二引数に集計 key とするカラム名(配列にすると multi index 集計)
・第三引数に辞書型で集計対象(key)と集計方法(value)を指定

例1.

julia> by(df, :C ,:A=>sum)
4×2 DataFrame
│ Row │ C      │ A_sum │
│     │ String │ Int64 │
├─────┼────────┼───────┤
│ 1   │ A      │ 5     │
│ 2   │ B      │ 2     │
│ 3   │ C      │ 13    │
│ 4   │ X      │ 5     │

例2.

julia> by(df, :C ,(:A=>sum, :A=>mean, :B=>std))
4×4 DataFrame
│ Row │ C      │ A_sum │ A_mean  │ B_std    │
│     │ String │ Int64 │ Float64 │ Float64  │
├─────┼────────┼───────┼─────────┼──────────┤
│ 1   │ A      │ 5     │ 2.5     │ 0.014525 │
│ 2   │ B      │ 2     │ 2.0     │ NaN      │
│ 3   │ C      │ 13    │ 6.5     │ 0.536156 │
│ 4   │ X      │ 5     │ 5.0     │ NaN      │

7.その他

sort 関数
第二引数で指定したカラム名でソート

julia> sort!(df, :B)
6×4 DataFrame
│ Row │ A     │ B        │ C      │ D     │
│     │ Int64 │ Float64  │ String │ Int64 │
├─────┼───────┼──────────┼────────┼───────┤
│ 1   │ 10    │ 0.1      │ C      │ 20    │
│ 2   │ 5     │ 0.142839 │ X      │ 200   │
│ 3   │ 2     │ 0.319128 │ B      │ 80    │
│ 4   │ 1     │ 0.558038 │ A      │ 40    │
│ 5   │ 4     │ 0.578579 │ A      │ 160   │
│ 6   │ 3     │ 0.858239 │ C      │ 120   │

降順

julia> sort!(df, :B, rev = true)
6×4 DataFrame
│ Row │ A     │ B        │ C      │ D     │
│     │ Int64 │ Float64  │ String │ Int64 │
├─────┼───────┼──────────┼────────┼───────┤
│ 1   │ 3     │ 0.858239 │ C      │ 120   │
│ 2   │ 4     │ 0.578579 │ A      │ 160   │
│ 3   │ 1     │ 0.558038 │ A      │ 40    │
│ 4   │ 2     │ 0.319128 │ B      │ 80    │
│ 5   │ 5     │ 0.142839 │ X      │ 200   │
│ 6   │ 10    │ 0.1      │ C      │ 20    │

カラム名の変更
rename 関数
例1. リストで変更

julia> new_colname = [:W, :X, :Y, :Z];
julia> rename!(df, new_colname)
6×4 DataFrame
│ Row │ W     │ X        │ Y      │ Z     │
│     │ Int64 │ Float64  │ String │ Int64 │
├─────┼───────┼──────────┼────────┼───────┤
│ 1   │ 3     │ 0.858239 │ C      │ 120   │
│ 2   │ 4     │ 0.578579 │ A      │ 160   │
│ 3   │ 1     │ 0.558038 │ A      │ 40    │
│ 4   │ 2     │ 0.319128 │ B      │ 80    │
│ 5   │ 5     │ 0.142839 │ X      │ 200   │
│ 6   │ 10    │ 0.1      │ C      │ 20    │

例2. 辞書で変更

julia> new_colname = Dict(:W=>:A, :X =>:B, :Y=>:C, :Z=>:D);
julia> rename!(df, new_colname)
6×4 DataFrame
│ Row │ A     │ B        │ C      │ D     │
│     │ Int64 │ Float64  │ String │ Int64 │
├─────┼───────┼──────────┼────────┼───────┤
│ 1   │ 3     │ 0.858239 │ C      │ 120   │
│ 2   │ 4     │ 0.578579 │ A      │ 160   │
│ 3   │ 1     │ 0.558038 │ A      │ 40    │
│ 4   │ 2     │ 0.319128 │ B      │ 80    │
│ 5   │ 5     │ 0.142839 │ X      │ 200   │
│ 6   │ 10    │ 0.1      │ C      │ 20    │
36
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?