Help us understand the problem. What is going on with this article?

Juliaで遊んでみた - データフレーム操作編

最近流行りつつある科学計算処理向けの高水準言語「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    
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした