裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

整数平方根 isqrt

2021年02月08日 | ブログラミング

整数 n に対して a^2 <= n を満たす最大の整数 a を求めるときは,
int(sqrt(n)) ではなくisqrt を使う

ということであるが,math に isqrt があるのは知らなくて,自分で関数を書いたりした。ニュートン法なのでそこそこの速度はあったのだけど。

from math import isqrt
from time import time

def f(n):
    a = isqrt(n)
    return a**2 <= n < (a+1)**2

start = time(); print(f(2**12345678), time()-start)
# True 37.5530788898468

Julia にも isqrt はあるが,実引数 n の指定には BigInt が使われるように定義すること。まあ,それだけだから,簡単といえば簡単だ。

function f(n)
    a = isqrt(n)
    a^2 <= n < (a+1)^2
end

@time f(BigInt(2)^12345678)
# 0.178914 seconds (1.44 k allocations: 51.893 MiB, 0.52% gc time)
# true

Python より 200 倍速い。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia で主成分分析(その2)

2021年02月05日 | ブログラミング

色々な指定とか,順をおって自分でやらないといけないことが多くて使いにくいなあと。

include でもして,簡単に使える関数に仕立てた。以下の 12 行だけ。

julia> using CSV, DataFrames, Statistics, StatsBase, LinearAlgebra
julia> function pca(data::DataFrame; scale::Bool =true)
           pca(Array{Float64,2}(data); scale)
       end
julia> function pca(data::Array{Float64,2}; scale::Bool =true)
           r = Symmetric((scale ? cor : cov)(data))
           eigenvalue, eigenvectors = eigen(r, sortby=x-> -x)
           eigenvalue = [x < 0 ? 0 : x for x in eigenvalue]
           temp = fit(ZScoreTransform, data, dims=1; center=true, scale)
           score = StatsBase.transform(temp, data) * eigenvectors
           return eigenvalue, eigenvectors, score
       end

データの準備

julia> using RDatasets
julia> iris = dataset("datasets", "iris");
julia> data = iris[:, 1:4];

使うのは簡単。データフレームなり配列を関数に渡すだけ。この場合は,データを平均値 0,標準偏差 1 にしてから分析する。

データの中に単位の異なる変数が含まれている場合や,変数の分散の違いが分析に支障を生ずるような場合にはこちら(scale=true)でなければならない。

返されるのは固有値,固有ベクトル,主成分得点。全ての主成分を抽出して返すので,何個の主成分を使うかはご自由に。

julia> val1, vec1, score1 = pca(iris[:, 1:4]);

第 1 主成分と第 2 主成分で全体の 96% ほども説明できる。

julia> sum(val1[1:2])/sum(val1)
0.9581320720000164

図を描いてみよう。

julia> using Plots
julia> col = vcat(fill(:green, 50), fill(:blue, 50), fill(:red, 50));
julia> scatter(score1[:, 1], score1[:, 2], markercolor=col, label="")

分散・共分散行列を対象にする(データを標準偏差で標準化しない)場合は,scale=false を指定する。

julia> val2, vec2, score2 = pca(iris[:, 1:4], scale=false);
julia> scatter(score2[:, 1], score2[:, 2], markercolor=col, label="")

R のときは,このようになる。

julia> using RCall
julia> R"""
       ans1 = prcomp(iris[,1:4], scale.=TRUE)
       color = rep(c("chartreuse4", "blue", "red"), each=50)
       plot(-ans1$x[,1], -ans1$x[,2], pch=19, col=color)
       ans2 = prcomp(iris[,1:4], scale.=FALSE)
       plot(-ans2$x[,1], -ans2$x[,2], pch=19, col=color)
       """

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia で主成分分析

2021年02月05日 | ブログラミング

最近は,主成分分析も機械学習の視点から使用されることが多いようだが,かなり違和感を感じる。

それはさておき,主成分分析の例示であるが,そのままでは Version 1.5.3 では動かないので,少し修正して掲載。

https://multivariatestatsjl.readthedocs.io/en/stable/pca.html

julia> using MultivariateStats, RDatasets, Plots
julia> plotly() # using plotly for 3D-interacive graphing
julia> iris = dataset("datasets", "iris"); # load iris dataset
julia> # split half to training set
       #
分析に使うデータ行列は列が観察値(つまり普通のデータ行列の転置!)
       Xtr = transpose(Array{Float64,2}(iris[1:2:end,1:4]));
julia> Xtr_labels = Array{String,1}(iris[1:2:end,5]);
julia> # split other half to testing set
       Xte = transpose(Array{Float64,2}(iris[2:2:end,1:4]));
julia> Xte_labels = Array{String,1}(iris[2:2:end,5]);
julia> # suppose Xtr and Xte are training and testing data matrix,
       # with each observation in a column
       # train a PCA model, allowing up to 3 dimensions
       M = fit(PCA, Xtr; maxoutdim=3)
PCA(indim = 4, outdim = 3, principalratio = 0.9957325846529409)
julia> # apply PCA model to testing set
       Yte = MultivariateStats.transform(M, Xte)
3×75 Array{Float64,2}:
  2.72714    2.75491     2.32396   2.65105     2.68917   …
 -0.230916  -0.406149    0.646374  0.0828144  -0.17411
  0.253119   0.0271266  -0.230469  0.0252853   0.231507
julia> # reconstruct testing observations (approximately)
       Xr = reconstruct(M, Yte)
4×75 Array{Float64,2}:
 4.86449  4.61087   5.40782   5.00775   4.90864   4.83689   …
 3.04262  3.08695   3.89061   3.39069   3.08963   3.35572
 1.46099  1.48132   1.68656   1.48668   1.48516   1.53664
 0.10362  0.229519  0.421233  0.221041  0.123445  0.300129
julia> # group results by testing set labels for color coding
       setosa = Yte[:,Xte_labels.=="setosa"]
3×25 Array{Float64,2}:
  2.72714    2.75491     2.32396   2.65105     2.68917   …
 -0.230916  -0.406149    0.646374  0.0828144  -0.17411
  0.253119   0.0271266  -0.230469  0.0252853   0.231507
julia> versicolor = Yte[:,Xte_labels.=="versicolor"]
3×25 Array{Float64,2}:
 -0.901049   -0.189593  -0.631938    0.737306   0.00578031  …
  0.350685   -0.7887    -0.40525    -1.01982   -0.74682
 -0.0027406   0.291058   0.0207768   0.121331  -0.179235
julia> virginica = Yte[:,Xte_labels.=="virginica"]
3×25 Array{Float64,2}:
 -1.4126    -1.95359   -3.35517   -2.89581   -2.8711    …
 -0.556727  -0.133821   0.692925   0.487134   0.828406
 -0.214115  -0.075898   0.293002   0.386084  -0.496979
julia> # visualize first 3 principal components in 3D interacive plot
       p = scatter(setosa[1,:],setosa[2,:],setosa[3,:],marker=:circle,linewidth=0)
julia> scatter!(versicolor[1,:],versicolor[2,:],versicolor[3,:],marker=:circle,linewidth=0)
julia> scatter!(virginica[1,:],virginica[2,:],virginica[3,:],marker=:circle,linewidth=0)
julia> plot!(p,xlabel="PC1",ylabel="PC2",zlabel="PC3")

その他,fit(PCA,...) が返すオブジェクトの出力

julia> indim(M) # 入力データ行列の次元数(変数の個数)
4

julia> outdim(M) # 結果の次元数(抽出された主成分の数)
3

julia> using Statistics

julia> mean(M) # 入力データの各変数の平均値
4-element Array{Float64,1}:
 5.839999999999999
 3.0640000000000005
 3.775999999999999
 1.2186666666666668

julia> projection(M) # 固有ベクトル(列が各主成分)
4×3 Array{Float64,2}:
 -0.3419     0.740952    0.505693
  0.109668   0.641943   -0.680395
 -0.857598  -0.171424   -0.0624452
 -0.368242  -0.0975392  -0.526723

julia> principalvars(M) # 固有値(求めた主成分の数だけ)
3-element Array{Float64,1}:
 4.306799211542801
 0.21643663210761893
 0.10023939904836703

julia> tprincipalvar(M) # 固有値の和(求めた主成分の数まで)
4.623475242698786

julia> tresidualvar(M) # 固有値全体の和からtprincipalvar(M) を引いたもの
0.019814847391297796

julia> tvar(M) # 固有値全体の和
4.643290090090084

全ての固有値は,4.30679921, 0.21643663, 0.10023940, 0.01981485

julia> principalratio(M) # 寄与率 tprincipalvar(M) / tvar(M)
0.9957325846529409

R では prcomp() で行う。

R> data = t($Xtr)

R> colMeans(data)
[1] 5.840000 3.064000 3.776000 1.218667

Julia では,データの中心化(平均値を0にする)はするが尺度調整(標準偏差を1にしない)はしないのでそれに合わせる(R でもデフォルトは Julia と同じ)

R> ans = prcomp(data, center = TRUE, scale. = FALSE)

R> ans$rotation # 固有ベクトル
            PC1        PC2         PC3        PC4
[1,]  0.3419004 -0.7409515  0.50569328 -0.2799450
[2,] -0.1096682 -0.6419429 -0.68039532  0.3360720
[3,]  0.8575983  0.1714240 -0.06244523  0.4808737
[4,]  0.3682420  0.0975392 -0.52672299 -0.7598992

R> ans$sdev^2 # 固有値
[1] 4.30679921 0.21643663 0.10023940 0.01981485

R> sum(ans$sdev^2) # tvar(M)
[1] 4.64329

R> sum(ans$sdev[1:3]^2) # tprincipalvar(M)
[1] 4.623475

R> test = t($Xte) # テストデータ
R> test2 = t(t(test) - colMeans(data)) # 平均値を 0 にする
R> score = test2 %*% ans$rotation[,1:3] # 主成分得点を計算

R> library(rgl) # 3次元散布図
R> plot3d(score$x[,1], score$x[,2], score$x[,3], col=rep(c("red", "black", "green"),each=25))

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

しんきろう(2)

2021年02月04日 | ブログラミング

もうだめだはこのひとははやくやめるべきやめさせるべきにほんおわったとおもわれるぞぶちぎれるなどもってのほか

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

COCOA って,命名がそもそもアホ

2021年02月04日 | 雑感

キラキラネームだね。みんな,喜んでダウンロード・インストールしてくれると思ったのかな?

そもそも,誰に通知が行ったかまでは個人情報保護の観点から把握しないのは当たり前だろうけど,何件くらい通知がされたかも把握していなかったのだろうか?

把握できていれば,通知が 0 なんて異常事態はすぐわかっただろうし。
どの地域でどれくらいの通知があったというのは感染状況把握の上で重大なデータだと思うのだけど,それすら把握していなかったのか?

というか,それくらいの情報は把握するように,厚労省なりなんなりが指示しなかったのだろうか???

アホの集団だったのだろうか。

指示されなくても,個人情報を保護しながらも,アプリが適切に動いているということも把握しようとしていなかったのか。

IT 企業ともてはやされているが,その頭のレベルがわかってしまった出来事だね。なさけない。

政府や厚労省には詫びなくてもいいけど,全国民にお詫びしなさい。全員,丸坊主にするのが手始めだね。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia で回帰分析(単回帰,重回帰)

2021年02月04日 | ブログラミング

参照元

https://multivariatestatsjl.readthedocs.io/en/stable/lreg.html


julia> using MultivariateStats
julia> using Statistics
julia> using Plots
julia> using Random
julia> Random.seed!(123);

例示のためのデータの準備

julia> X = rand(1000, 3);               # feature matrix
julia> a0 = rand(3);                    # ground truths
julia> y = X * a0 + 0.1 * randn(1000);  # generate response

llsq の使用法

julia>
a = llsq(X, y; bias=false);
julia> println(a)
[0.245462794630527, 0.39679768213855493, 0.8727270841084174]

それぞれが何を指すかは,あとの R スクリプトの結果を参照のこと

予測

julia>
yp = X * a;

図を描いてみる

julia> scatter(y, yp, label="")

誤差の評価

julia>
rmse = sqrt(mean(abs2.(y .- yp)));
julia> print("rmse = $rmse")
rmse = 0.1048730072098373

R であれば,

julia> using RCall
julia> R"""
       options(digits=15)
       lm($y ~$X+0)
       """
RObject{VecSxp}

Call:
lm(formula = `#JL`$y ~ `#JL`$X + 0)

Coefficients:
      `#JL`$X1        `#JL`$X2        `#JL`$X3  
0.245462794631  0.396797682139  0.872727084108  

切片ありの場合(デフォルト) biase=true

julia> a = llsq(X, y)
julia> println(a)
[0.24257522344490817, 0.3941270828348356, 0.8700648276936214, 0.0044911156001156615]

R でやると

julia> R"lm($y ~$X)"
RObject{VecSxp}

Call:
lm(formula = `#JL`$y ~ `#JL`$X)

Coefficients:
     (Intercept)          `#JL`$X1          `#JL`$X2          `#JL`$X3  
0.00449111560012  0.24257522344490  0.39412708283483  0.87006482769362  

単回帰の場合にはちょっと面倒

julia> x1 = reshape(X[:, 1], size(X, 1), :);
julia> a = llsq(x1, y);
julia> println(a)
[0.19497651423072845, 0.6432936814951281]

R ならば

julia> R"lm($y ~ $x1)"
RObject{VecSxp}

Call:
lm(formula = `#JL`$y ~ `#JL`$x1)

Coefficients:
   (Intercept)        `#JL`$x1  
0.643293681495  0.194976514231  

 

★★ 代替法として,GLM を使えば,R と同じような感じで分析できるよ。

(こっちがお勧め)

julia> using GLM
julia> using DataFrames
julia> df = DataFrame(X);
julia> insertcols!(df, 4, :y => y);
julia> lm(@formula(y ~ x1 + x2 + x3), df)
StatsModels.TableRegressionModel{LinearModel{GLM.LmResp{Array{Float64,1}},GLM.DensePredChol{Float64,LinearAlgebra.Cholesky{Float64,Array{Float64,2}}}},Array{Float64,2}}

y ~ 1 + x1 + x2 + x3

Coefficients:
───────────────────────────────────────────────────────────────────────────
                  Coef.  Std. Error      t  Pr(>|t|)   Lower 95%  Upper 95%
───────────────────────────────────────────────────────────────────────────
(Intercept)  0.00449112   0.0107952   0.42    0.6775  -0.0166928   0.025675
x1           0.242575     0.0118303  20.50    
x2           0.394127     0.01155    34.12    
x3           0.870065     0.0116234  74.85    
───────────────────────────────────────────────────────────────────────────

julia> lm(@formula(y ~ x1 + x2 + x3 + 0), df)
StatsModels.TableRegressionModel{LinearModel{GLM.LmResp{Array{Float64,1}},GLM.DensePredChol{Float64,LinearAlgebra.Cholesky{Float64,Array{Float64,2}}}},Array{Float64,2}}

y ~ 0 + x1 + x2 + x3

Coefficients:
───────────────────────────────────────────────────────────────
       Coef.  Std. Error      t  Pr(>|t|)  Lower 95%  Upper 95%
───────────────────────────────────────────────────────────────
x1  0.245463  0.0095763   25.63    
x2  0.396798  0.00959782  41.34    
x3  0.872727  0.00969927  89.98    
───────────────────────────────────────────────────────────────

julia> lm(@formula(y ~ x1), df)
StatsModels.TableRegressionModel{LinearModel{GLM.LmResp{Array{Float64,1}},GLM.DensePredChol{Float64,LinearAlgebra.Cholesky{Float64,Array{Float64,2}}}},Array{Float64,2}}

y ~ 1 + x1

Coefficients:
────────────────────────────────────────────────────────────────────────
                Coef.  Std. Error      t  Pr(>|t|)  Lower 95%  Upper 95%
────────────────────────────────────────────────────────────────────────
(Intercept)  0.643294   0.0188953  34.05    
x1           0.194977   0.0327767   5.95    
────────────────────────────────────────────────────────────────────────

まあ,そんなところ。

決定係数を出したりはまた後で。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia でのデータフレームの読み書き(とどめ!)

2021年02月04日 | ブログラミング

https://dataframes.juliadata.org/stable/man/getting_started/ 
の一番最後で以下が推奨されているので,それ以外の方法については書かない方がよい。

去年の夏の時点での記事や v. 1.5.2 ですら 今や deprecated なので,不適切な情報は広めないで欲しい。

using CSV
DataFrame(CSV.File(input))
CSV.write(output, df)

ただし,オプションを設定するためには,以下を使うべし。

CSV.read(input, DataFrame; kwargs)

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia でヒートマップ

2021年02月04日 | ブログラミング

某所で,Julia ではヒートマップを簡単に描くことができないとこぼしている人がいた。その人は行と列の並べ替えすらしないで,もっと簡単に描けないのかと言っている。
ヒートマップって,データのビジュアライゼーションという点ではそんなに優れているものとも思わないが,せめて適切に行と列を並べないと何の意味もないグラフができてしまうだけだ。

julia> using PyPlot, Plots, DataFrames, CSV
julia> pyplot()
julia> using Random
julia> Random.seed!(123)
julia> df = DataFrame(Location = ["NY", "SF", "NY", "NY", "SF", "SF", "TX", "TX", "TX", "DC", "DC", "DC"],
                      Class = ["M","M","H","L","L","H", "H","L","M","M","H","L"],
                      Score = rand(12))
12×3 DataFrame
 Row │ Location  Class   Score     
     │ String    String  Float64   
─────┼─────────────────────────────
   1 │ NY        M       0.768448
   2 │ SF        M       0.940515
   3 │ NY        H       0.673959
   4 │ NY        L       0.395453
   5 │ SF        L       0.313244
   6 │ SF        H       0.662555
   7 │ TX        H       0.586022
   8 │ TX        L       0.0521332
   9 │ TX        M       0.26864
  10 │ DC        M       0.108871
  11 │ DC        H       0.163666
  12 │ DC        L       0.473017

julia> CSV.write("data.csv", df)

縦軸にLocation, 横軸にClassを持つピボットテーブルに変形する

julia> pivot = DataFrames.unstack(data, :Location, :Class, :Score)
4×4 DataFrame
 Row │ Location  M         H         L         
     │ String    Float64?  Float64?  Float64?  
─────┼─────────────────────────────────────────
   1 │ NY        0.768448  0.673959  0.395453
   2 │ SF        0.940515  0.662555  0.313244
   3 │ TX        0.26864   0.586022  0.0521332
   4 │ DC        0.108871  0.163666  0.473017

ここまでだと,行も列も乱雑に並んでいるだけなので,適切に並べ替える。データフレームの操作は色々方法があるが,Query を使う例を挙げておく。

julia> using Query
julia> pivot2 = pivot |>
         @select(1, 4, 2, 3) |>
         @orderby(_.Location) |> DataFrame
4×4 DataFrame
 Row │ Location  L          M         H        
     │ String    Float64?   Float64?  Float64? 
─────┼─────────────────────────────────────────
   1 │ DC        0.473017   0.108871  0.163666
   2 │ NY        0.395453   0.768448  0.673959
   3 │ SF        0.313244   0.940515  0.662555
   4 │ TX        0.0521332  0.26864   0.586022

julia> x = names(pivot2)[2:end]
3-element Array{String,1}:
 "L"
 "M"
 "H"

julia> y = pivot2.Location
4-element Array{String,1}:
 "DC"
 "NY"
 "SF"
 "TX"

julia> heatmap(x, y, Matrix(pivot2[:, 2:4]))

freqtable を使うやり方では行と列は辞書順になるが,任意の行と列の並べ替えはたいへんなので,そのまま描画。

julia>
using DataFrames, FreqTables, NamedArrays
julia> using Plots
julia> pivot3 = freqtable(data, :Class, :Location, weights=-df.Score)
3×4 Named Array{Float64,2}
Class ╲ Location │        DC         NY         SF         TX
─────────────────┼───────────────────────────────────────────
H                │  0.163666   0.673959   0.662555   0.586022
L                │  0.473017   0.395453   0.313244  0.0521332
M                │  0.108871   0.768448   0.940515    0.26864

julia> heatmap(pivot3)

行と列の並べ替えを簡単にできるように,意味のある並べ替えが自動的にできるように,色使いも選べるように,ブロック中に数値を描けるようにとか,要望は多々ある。

ないものは,作る,しか,ないの,かな?

いやいや,R がもうあるんだから,それでいいだろう。R の heatmap を使うべし。

julia> rownames, colnames = names(pivot3)
julia> using RCall
julia> R"""
       mat = $pivot3
       colnames(mat) = $colnames
       rownames(mat) = $rownames
       heatmap(mat)
       """

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

COCOA 不具合

2021年02月04日 | ブログラミング

新型コロナウイルスの接触確認アプリ「COCOA」に不具合が見つかり、アンドロイド版で去年の秋以降、感染者と接触した可能性のあるアプリの利用者に通知が届いていないことがわかりました。

なんか,うさんくさかったねえ。

インストールしなくて,本当によかった。くそアプリというか,詐欺アプリじゃないか。金を取られなかっただけまだマシか(^_^;)

いかに,このアプリが信頼されていなかったかということにつきる。

信頼していないというか,気にも掛けていないから,インストールしようとも思わない。

別に気に掛けてもいないから,インストールしたとしても,アプリの動作結果がどうであるかしらない。

アプリの動作が変であったとしても,気づかないし,きづいても通知すらしない。

そもそも,アプリがちゃんと働いているかなんて,わかりようがない。

う??,そんなあぷり,あったの?

あったの知ってるけど,インストールしようなんて思わなかった。

インストールなんかしなくてよかったわあ。

これからも,おんなじようなアプリがあっても,インストールなんか絶対しないからな!!!ばかやろう。

もう,だめだわこりゃ。終わったな,日本政府。

 

 

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

しんきろう!

2021年02月03日 | 雑感

有名人が聖火ランナーを務めて,市中を走ると,多くの人が集まってしまって困ると。

 

だったら,聖火ランナーはたんぼ道を走れと。そうすれば,人は集まらないだろうから,いいんじゃないかと。

 

おまえは,こどもか?

 

分別ある子供,三歳児でも,そんなことは言わないだろう。なげかわしい。

 

老害の域を超えている。だれか,止める人はいないのか?

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia で データフレームの入出力

2021年02月03日 | ブログラミング

== https://csv.juliadata.org/stable/#Getting-Started

== ファイルからデータフレームへの読み込み

以下のような内容を持つ small.csv ファイルを入力対象とする。

julia> run(`cat small.csv`)
a, b, c
1, 0.1, 34
2, 1, 54
3, 10, 0.4
4, 99, 554

julia> run(`cat small2.csv`)
a, 0.1, 34
b, 1, 54
c, 10, 0.4
d, 99, 554

csv ファイルをデータフレームに読み込むのは,以下のようにするのが一番簡単である。

julia> using CSV, DataFrames
julia> df = CSV.read("small.csv", DataFrame)
4×3 DataFrame
 Row │ a       b        c      
     │ Int64  Float64  Float64 
─────┼─────────────────────────
   1 │     1      0.1     34.0
   2 │     2      1.0     54.0
   3 │     3     10.0      0.4
   4 │     4     99.0    554.0

== 引数

header=整数
  列名の定義について指定する。省略されている場合は,適当に解釈される。
  列名が何行目に定義されているかを指定する。
  デフォルトでは header=1。
  2 以上の値が指定されたときはそれまでの行は読み飛ばされる。
  また,列名の指定行のすぐ後からデータが始まると解釈されるので,
  もし読み飛ばすべき行があるならば,skipto, datarow でデータ開始行を指定する。
  df = CSV.read("small.csv", DataFrame, header=0, skipto=2)
header=0 もしくは header=false
  列名を持たないファイルの場合は,列名を自動生成することができる。
  df = CSV.read("small2.csv", DataFrame, header=0)
header=["ab", "cd", ...]
  文字列ベクトルで列名定義
  df = CSV.read("small2.csv", DataFrame, header=["a1", "b1", "c1"])
header=[:ab, :cd, ...]
  シンボルベクトルで列名定義
  df = CSV.read("small2.csv", DataFrame, header=[:a, :b, :c]])
normalizenames=false
  列名の正規化をする
datarow
  データが始まる行番号
skipto
  データが始まる行番号 datarow と同じ
footerskip
  データの最後の何行を読み飛ばすかを指定
limit
  入力行数の制限
transpose=false
  行と列を転置して入力
comment
  指定した文字列から始まる行を(コメント行として)読み飛ばす
ignoreemptylines=true
  空行を読み飛ばす
select
  選択する行をベクトルで指定する
  select=[1, 3] 列番号で指定
  select=[:a, :c] 列シンボルで指定
  select=["a", "c"] 列名で指定
  select=[true, false, true] 論理値で指定
  select=(i, nm) -> i in (1, 3) ラムダ式(無名関数)で指定
drop
  選択しない行をベクトルで指定する(select の逆)
missingstrings, missingstring
  欠損値
  missingstring="-999"
  missingstrings=["-999", "NA"]
delim=','
  データのデリミター
  最初の 10 行を見て,',', '\t', ' ', '|', ';', ':' のどれかをデリミターと解釈する
  delim="@@@" のように文字列も使える
ignorerepeated=false
  連続するデリミタを無視するか
  複数の空白で桁位置を揃えて入力されたファイルを読むときなどに,
  delim=' ', ignorerepeated=true を指定すればよい。
quotechar='"'
  文字列をくくる引用符
escapechar='"'
  引用符のエスケープ文字
dateformat
  日付,時間のフォーマットを示す文字列
  dateformat="yyyy/mm/dd" など
dateformats
  日付,時間のフォーマットを辞書型で示す
decimal='.'
  小数点を表す文字
truestrings=["T", "TRUE"]
  true の他に真値を表す文字列の定義
falsestrings=["F", "FALSE"]
  false の他に真値を表す文字列の定義
type
  ファイル全体に共通する唯一のデータ型
  項目全てをここで指定した型として読む
  実数データ行列を読むときに type=Float64 のように指定する
types
  列ごとのデータ型
  ベクトルで与える場合は,全ての列について定義する
  types=Dict(3 => Int)
  types=Dict(:col3 => Int)
  types=Dict("col3" => Float64)
  types=[Int, Float64, String]
typemap
  特定の型の入力値を別の型として読み込む
  型のマッピング Dict(Float64=>String) のように指定
  typemap=Dict(Int => String)
  types=Dict(:zipcode => String)
pool
lazystrings=false
strict=false
  不正な値は警告して missing にする
silencewarnings=false
  strict=false のとき,不正な値の警告はしない
maxwarnings=100
  警告を表示する最高回数

== エンコーディングの違うファイルを読む

Windows で作られた日本語を含むファイルは,以下のようにして読む(shift_jis などではなく,cp932 を指定する)。
他にサポートされているエンコーディングは encodings() で参照できる。

julia> using StringEncodings
julia> CSV.File(open(read, "cp932.csv", enc"cp932")) |> DataFrame
2×3 DataFrame
 Row │ 日本語  ファイル  数値  
     │ Int64   Int64     Int64 
─────┼─────────────────────────
   1 │      1         2      3
   2 │      4         5      6

== gzip ファイルを読む

以下のようにして作られた gzip ファイルを読む。

読み込み法を示すためのテストデータの作成

julia> using CSV, DataFrames, CodecZlib, Mmap
julia> a = DataFrame(a = 1:3)
3×1 DataFrame
 Row │ a     
     │ Int64 
─────┼───────
   1 │     1
   2 │     2
   3 │     3

julia> CSV.write("a.csv", a)
"a.csv"

julia> run(`gzip a.csv`) # a.csv.gz ができる
a.csv.gz already exists -- do you wish to overwrite (y or n)? y
Process(`gzip a.csv`, ProcessExited(0))

a.csv.gz を読む

julia> a_copy = CSV.File(transcode(GzipDecompressor, Mmap.mmap("a.csv.gz"))) |> DataFrame
3×1 DataFrame
 Row │ a     
     │ Int64 
─────┼───────
   1 │     1
   2 │     2
   3 │     3

julia> a == a_copy # 同じであることを確認
true

== zip ファイルを読む

読み込み例を示すためのテスト用のファイルを作る

julia> using ZipFile, CSV, DataFrames
julia> a = DataFrame(a = 1:3)
3×1 DataFrame
 Row │ a     
     │ Int64 
─────┼───────
   1 │     1
   2 │     2
   3 │     3

julia> CSV.write("a.csv", a)
"a.csv"
julia> run(`zip a.zip a.csv`) # a.zip ファイルができる

updating: a.csv (stored 0%)
Process(`zip a.zip a.csv`, ProcessExited(0))

a.zip というファイルを読む

julia> z = ZipFile.Reader("a.zip")
ZipFile.Reader for IOStream() containing 1 files:

uncompressedsize method  mtime            name
----------------------------------------------
               8 Store   2021-02-03 15-55 a.csv

まだ続く

julia> a_file_in_zip = filter(x->x.name == "a.csv", z.files)[1]
ZipFile.ReadableFile(name=a.csv, method=Store, uncompresssedsize=8, compressedsize=8, mtime=1.612335328e9)

julia> a_copy = CSV.File(read(a_file_in_zip)) |> DataFrame
3×1 DataFrame
 Row │ a     
     │ Int64 
─────┼───────
   1 │     1
   2 │     2
   3 │     3


== データフレームを csv ファイルに書き出す

CSV.write(ファイル, table)
table |> CSV.write(ファイル)

引数

bufsize=2^22
  バッファーサイズ
delim=','
  デリミター
quotechar='"'
  引用符
escapechar='"'
  引用符のエスケープ文字
missingstring=""
  missing を表す文字列
dateformat
  dateformat="yyyy/mm/dd" など append=false
  既存のファイルに書き足すかどうか
writeheader=!append
  列名を出力するか
header
  使用する列名のリスト
newline='\n'
  改行文字
quotestrings=false
  文字列を引用符で囲むかどうか
decimal='.'
  小数点として使用する文字
transform
bom=false
partition=false

== その他の基礎的な入力方方法

read(``small.csv'') は バイト列を返す。

julia> read("small.csv")[1:5]
5-element Array{UInt8,1}:
 0x61
 0x2c
 0x20
 0x62
 0x2c

CSV.File は CSV.File オブジェクトを返す。

julia> CSV.File("small.csv")
4-element CSV.File{false}:
 CSV.Row: (a = 1,  b = 0.1,  c = 34.0)
 CSV.Row: (a = 2,  b = 1.0,  c = 54.0)
 CSV.Row: (a = 3,  b = 10.0,  c = 0.4)
 CSV.Row: (a = 4,  b = 99.0,  c = 554.0)

julia> CSV.File(read("small.csv")) # 前述の CSV.File("small.csv")  と同じ
4-element CSV.File{false}:
 CSV.Row: (a = 1,  b = 0.1,  c = 34.0)
 CSV.Row: (a = 2,  b = 1.0,  c = 54.0)
 CSV.Row: (a = 3,  b = 10.0,  c = 0.4)
 CSV.Row: (a = 4,  b = 99.0,  c = 554.0)

julia> read("small.csv") |> CSV.File # CSV.File("small.csv") と同じ
4-element CSV.File{false}:
 CSV.Row: (a = 1,  b = 0.1,  c = 34.0)
 CSV.Row: (a = 2,  b = 1.0,  c = 54.0)
 CSV.Row: (a = 3,  b = 10.0,  c = 0.4)
 CSV.Row: (a = 4,  b = 99.0,  c = 554.0)

以上の 3 通りの後に,さらに DataFrame
へパイプを繋げば,データフレームとして読まれる。

julia> CSV.File("small.csv") |> DataFrame
4×3 DataFrame
 Row │ a       b        c      
     │ Int64  Float64  Float64 
─────┼─────────────────────────
   1 │     1      0.1     34.0
   2 │     2      1.0     54.0
   3 │     3     10.0      0.4
   4 │     4     99.0    554.0

julia> CSV.File(read("small.csv"))  |> DataFrame
4×3 DataFrame
 Row │ a       b        c      
     │ Int64  Float64  Float64 
─────┼─────────────────────────
   1 │     1      0.1     34.0
   2 │     2      1.0     54.0
   3 │     3     10.0      0.4
   4 │     4     99.0    554.0

julia> read("small.csv") |> CSV.File |> DataFrame
4×3 DataFrame
 Row │ a       b        c      
     │ Int64  Float64  Float64 
─────┼─────────────────────────
   1 │     1      0.1     34.0
   2 │     2      1.0     54.0
   3 │     3     10.0      0.4
   4 │     4     99.0    554.0

CSV.Rows は行イテレータを返すが,特に指定しなければ全て文字列として読まれる。

julia> CSV.Rows("small.csv")
CSV.Rows("small.csv"):
Size: 3
Tables.Schema:
 :a            Union{Missing, String}
 Symbol(" b")  Union{Missing, String}
 Symbol(" c")  Union{Missing, String}

julia> CSV.Rows(read("small.csv"))
CSV.Rows(""):
Size: 3
Tables.Schema:
 :a            Union{Missing, String}
 Symbol(" b")  Union{Missing, String}
 Symbol(" c")  Union{Missing, String}

julia> read("small.csv") |> CSV.Rows
CSV.Rows(""):
Size: 3
Tables.Schema:
 :a            Union{Missing, String}
 Symbol(" b")  Union{Missing, String}
 Symbol(" c")  Union{Missing, String}

以上の 3 通りの後に,さらに DataFrame
へパイプを繋げば,データフレームとして読まれる。ただし,特に指定しなければ全て文字列として読まれる。

julia> CSV.Rows("small.csv") |> DataFrame
4×3 DataFrame
 Row │ a         b        c      
     │ String?  String?  String? 
─────┼───────────────────────────
   1 │ 1         0.1      34
   2 │ 2         1        54
   3 │ 3         10       0.4
   4 │ 4         99       554

julia> CSV.Rows(read("small.csv")) |> DataFrame
4×3 DataFrame
 Row │ a         b        c      
     │ String?  String?  String? 
─────┼───────────────────────────
   1 │ 1         0.1      34
   2 │ 2         1        54
   3 │ 3         10       0.4
   4 │ 4         99       554

julia> read("small.csv") |> CSV.Rows |> DataFrame
4×3 DataFrame
 Row │ a         b        c      
     │ String?  String?  String? 
─────┼───────────────────────────
   1 │ 1         0.1      34
   2 │ 2         1        54
   3 │ 3         10       0.4
   4 │ 4         99       554

列の内容に従ってデータフレームに読み込むには,CSV.File(ファイル名) |> DataFrame が簡単であろう。
読み取ったデータフレームは,変数に代入する。

julia> df = CSV.File("small.csv") |> DataFrame
4×3 DataFrame
 Row │ a       b        c      
     │ Int64  Float64  Float64 
─────┼─────────────────────────
   1 │     1      0.1     34.0
   2 │     2      1.0     54.0
   3 │     3     10.0      0.4
   4 │     4     99.0    554.0

以下のようにすればよさそうに思うかも知れないが,パイプは使えない。
CSV.File(``small.csv'') |> DataFrame |> df

データフレームからさらにパイプを繋いで配列にするときには以下のようにすればよい。
配列の場合は,全ての要素が同じ型に変換されることに注意。

julia> M = CSV.File("small.csv") |> DataFrame |> Matrix
4×3 Array{Float64,2}:
 1.0   0.1   34.0
 2.0   1.0   54.0
 3.0  10.0    0.4
 4.0  99.0  554.0

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Juliaでcsvに読み書き

2021年02月01日 | ブログラミング

juliaでcsvに読み書きするという記事があったのだが

「CSV.read()を上手く使えず, 手こずった」というのが理解不能だった。

julia(v1.5.2) ということなのだが,最新バージョンは Version 1.5.3 (2020-11-09) なので,まずは,最新バージョンにアップデートをお勧めします。

で,v1.5.3 での話なのですが,

df = CSV.read("foo.csv", DataFrame)

で,問題なく読めます。

書き出しも,

CSV.write("foo2.csv", df)

で,問題ありません。

区切りを ", " とするかどうかは,好みでしょうから。

(余計なことですが ./ はカレントディレクトリを示すだけなので,省略できます)

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia でクエリー(クエリー演算子-2)

2021年02月01日 | ブログラミング

@take コマンド

最初から幾つの要素を取り出すかを指示する

julia> source = [1,2,3,4,5]
5-element Array{Int64,1}:
 1
 2
 3
 4
 5

julia> q = source |> @take(3) |> collect
[1, 2, 3]

@drop コマンド

最初から幾つの要素を捨てるかを指示する。

julia> source = [1,2,3,4,5]
5-element Array{Int64,1}:
 1
 2
 3
 4
 5

julia> q = source |> @drop(3) |> collect
[4, 5]

@unique コマンド

重複データを取り除く(ユニークなデータのみを残す)

julia> source = [1,1,2,2,3]
5-element Array{Int64,1}:
 1
 1
 2
 2
 3

julia> q = source |> @unique() |> collect
[1, 2, 3]

@select コマンド

source |> @select(selectors...)

selector は名前,位置,述語関数で選択,排除を指定する,これらは順に適用される(順序が変更されることはない)。

julia> df = DataFrame(fruit=["Apple","Banana","Cherry"],amount=[2,6,1000],
                      price=[1.2,2.0,0.4],isyellow=[false,true,false])
3×4 DataFrame
 Row │ fruit   amount  price    isyellow 
     │ String  Int64   Float64  Bool     
─────┼───────────────────────────────────
   1 │ Apple        2      1.2     false
   2 │ Banana       6      2.0      true
   3 │ Cherry    1000      0.4     false

julia> q1 = df |> @select(2:3, occursin("ui"), -:amount) |> DataFrame
3×2 DataFrame
 Row │ price    fruit  
     │ Float64  String 
─────┼─────────────────
   1 │     1.2  Apple
   2 │     2.0  Banana
   3 │     0.4  Cherry


julia> df = DataFrame(fruit=["Apple","Banana","Cherry"],amount=[2,6,1000],
                      price=[1.2,2.0,0.4],isyellow=[false,true,false])
3×4 DataFrame
 Row │ fruit   amount  price    isyellow 
     │ String  Int64   Float64  Bool     
─────┼───────────────────────────────────
   1 │ Apple        2      1.2     false
   2 │ Banana       6      2.0      true
   3 │ Cherry    1000      0.4     false

julia> q2 = df |> @select(!endswith("t"), 1) |> DataFrame
3×3 DataFrame
 Row │ price    isyellow  fruit  
     │ Float64  Bool      String 
─────┼───────────────────────────
   1 │     1.2     false  Apple
   2 │     2.0      true  Banana
   3 │     0.4     false  Cherry

@rename コマンド

source |> @rename(args...)
args は順に適用される

julia> df = DataFrame(fruit=["Apple","Banana","Cherry"],amount=[2,6,1000],
                      price=[1.2,2.0,0.4],isyellow=[false,true,false])
3×4 DataFrame
 Row │ fruit   amount  price    isyellow 
     │ String  Int64   Float64  Bool     
─────┼───────────────────────────────────
   1 │ Apple        2      1.2     false
   2 │ Banana       6      2.0      true
   3 │ Cherry    1000      0.4     false

julia> q = df |> @rename(:fruit => :food, :price => :cost, :food => :name) |> DataFrame
3×4 DataFrame
 Row │ name    amount  cost     isyellow 
     │ String  Int64   Float64  Bool     
─────┼───────────────────────────────────
   1 │ Apple        2      1.2     false
   2 │ Banana       6      2.0      true
   3 │ Cherry    1000      0.4     false

@mutate コマンド

julia> df = DataFrame(fruit=["Apple","Banana","Cherry"],amount=[2,6,1000],
                      price=[1.2,2.0,0.4],isyellow=[false,true,false])
3×4 DataFrame
 Row │ fruit   amount  price    isyellow 
     │ String  Int64   Float64  Bool     
─────┼───────────────────────────────────
   1 │ Apple        2      1.2     false
   2 │ Banana       6      2.0      true
   3 │ Cherry    1000      0.4     false

julia> q = df |> @mutate(price = 2 * _.price + _.amount, isyellow = _.fruit == "Apple") |> DataFrame
3×4 DataFrame
 Row │ fruit   amount  price    isyellow 
     │ String  Int64   Float64  Bool     
─────┼───────────────────────────────────
   1 │ Apple        2      4.4      true
   2 │ Banana       6     10.0     false
   3 │ Cherry    1000   1000.8     false

@dropna コマンド

source |> @dropna(columns...)
引数なしで @dropna() のように使用されるときは,全ての列が対象になる。

julia> df = DataFrame(a=[1,2,3], b=[4,missing,5])
3×2 DataFrame
 Row │ a      b       
     │ Int64  Int64?  
─────┼────────────────
   1 │     1        4
   2 │     2  missing 
   3 │     3        5

julia> q = df |> @dropna() |> DataFrame
2×2 DataFrame
 Row │ a      b     
     │ Int64  Int64 
─────┼──────────────
   1 │     1      4
   2 │     3      5

julia> q = df |> @dropna(:b) |> DataFrame
2×2 DataFrame
 Row │ a      b     
     │ Int64  Int64 
─────┼──────────────
   1 │     1      4
   2 │     3      5

julia> q = df |> @dropna(:b, :a) |> DataFrame
julia> println(q)
2×2 DataFrame
 Row │ a      b     
     │ Int64  Int64 
─────┼──────────────
   1 │     1      4
   2 │     3      5

@dissallowna コマンド

source |> @dissallowna(columns...)
@dissallowna() のように引数なしで使われると全ての列を対象にする。

julia> df = DataFrame(a=[1,missing,3], b=[4,5,6])
3×2 DataFrame
 Row │ a        b     
     │ Int64?   Int64 
─────┼────────────────
   1 │       1      4
   2 │ missing      5
   3 │       3      6

julia> q = df |> @filter(!isna(_.a)) |> @dissallowna() |> DataFrame
2×2 DataFrame
 Row │ a      b     
     │ Int64  Int64 
─────┼──────────────
   1 │     1      4
   2 │     3      6

julia> df = DataFrame(a=[1,2,missing], b=[4,missing,5])
3×2 DataFrame
 Row │ a        b       
     │ Int64?   Int64?  
─────┼──────────────────
   1 │       1        4
   2 │       2  missing 
   3 │ missing        5

julia> q = df |> @filter(!isna(_.b)) |> @dissallowna(:b) |> DataFrame
2×2 DataFrame
 Row │ a        b     
     │ Int64?   Int64 
─────┼────────────────
   1 │       1      4
   2 │ missing      5

@replacena コマンド

source |> @replacena(replacement_value)

julia> df = DataFrame(a=[1,missing,3], b=[4,5,6])
3×2 DataFrame
 Row │ a        b     
     │ Int64?   Int64 
─────┼────────────────
   1 │       1      4
   2 │ missing      5
   3 │       3      6

julia> q = df |> @replacena(0) |> DataFrame
3×2 DataFrame
 Row │ a      b     
     │ Int64  Int64 
─────┼──────────────
   1 │     1      4
   2 │     0      5
   3 │     3      6

julia> df = DataFrame(a=[1,2,missing], b=["One",missing,"Three"])
3×2 DataFrame
 Row │ a        b       
     │ Int64?   String? 
─────┼──────────────────
   1 │       1  One
   2 │       2  missing 
   3 │ missing  Three

julia> q = df |> @replacena(:b=>"Unknown", :a=>0) |> DataFrame
3×2 DataFrame
 Row │ a      b       
     │ Int64  String  
─────┼────────────────
   1 │     1  One
   2 │     2  Unknown
   3 │     0  Three

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia でクエリー(クエリー演算子-1)

2021年02月01日 | ブログラミング

スタンドアローンのクエリー演算子

スタンドアローンのクエリー演算子はパイプ演算子 |> で組み合わせて使われる。

julia> using Query, DataFrames, Statistics

julia> df = DataFrame(a=[1,1,2,3], b=[4,5,6,8])
4×2 DataFrame
 Row │ a      b     
     │ Int64  Int64 
─────┼──────────────
   1 │     1      4
   2 │     1      5
   3 │     2      6
   4 │     3      8

julia> df2 = df |>
           @groupby(_.a) |>
           @map({a=key(_), b=mean(_.b)}) |>
           @filter(_.b > 5) |>
           @orderby_descending(_.b) |>
           DataFrame
2×2 DataFrame
 Row │ a      b       
     │ Int64  Float64 
─────┼────────────────
   1 │     3      8.0
   2 │     2      6.0

@map コマンド

source |> @map(element_selector)
source は,クエリーできるものなら何でもよい(これ以降の全てのコマンドの場合も同じ)。
下の例ではベクトルが対象にされている。

以下の例は,ベクトルから要素を 1 個ずつ取り出し 2 乗して,結果を集め,x に代入する。

julia> data = [1,2,3];
julia> x = data |> @map(_^2) |> collect
[1, 4, 9]

@filter コマンド

source |> @filter(filter_condition)
filter_condition は,ソースから 1 つの要素を受け取りその要素を保持する場合に true,フィルターされる場合には false を返す無名関数

julia> df = DataFrame(name=["John", "Sally", "Kirk"],
                      age=[23., 42., 59.], children=[3,5,2])

3×3 DataFrame
 Row │ name    age      children 
     │ String  Float64  Int64    
─────┼───────────────────────────
   1 │ John       23.0         3
   2 │ Sally      42.0         5
   3 │ Kirk       59.0         2

julia> x = df |> @filter(_.age > 30 && _.children > 2) |> DataFrame
1×3 DataFrame
 Row │ name    age      children 
     │ String  Float64  Int64    
─────┼───────────────────────────
   1 │ Sally      42.0         5

@groupby コマンド

source |> @groupby(key_selector)
key_selector は,ソースの要素がグループ化されるときに使われる値を返す無名関数

source |> @groupby(source, key_selector, element_selector)
element_selector ソースの要素がグループ分けされる前にグループの前に挿入される要素に適用される無名関数

@group の戻り値はグループのイテラブルである。

julia> df = DataFrame(name=["John", "Sally", "Kirk"],
                      age=[23., 42., 59.], children=[3,2,2])

3×3 DataFrame
 Row │ name    age      children 
     │ String  Float64  Int64    
─────┼───────────────────────────
   1 │ John       23.0         3
   2 │ Sally      42.0         2
   3 │ Kirk       59.0         2

julia> x = df |>
           @groupby(_.children) |> # children でグループ化
           @map({Key=key(_), Count=length(_)}) |> # Count はサイズ
           DataFrame
2×2 DataFrame
 Row │ Key    Count 
     │ Int64  Int64 
─────┼──────────────
   1 │     3      1
   2 │     2      2

@orderby コマンド
@orderby_descenidng コマンド

データのソート(昇順,降順)

@thenby コマンド
@thenby_descending コマンド

直前のデータソートに続いてデータのソートを行う(昇順,降順)。直前のソートで同順位があった場合の処理を定義する。
source |> @orderby(key_selector)
@orderby(key_selector) |> @thenby(key_selector2)

julia> df = DataFrame(a=[2,1,1,2,1,3],b=[2,2,1,1,3,2])
6×2 DataFrame
 Row │ a      b     
     │ Int64  Int64 
─────┼──────────────
   1 │     2      2
   2 │     1      2
   3 │     1      1
   4 │     2      1
   5 │     1      3
   6 │     3      2

julia> x = df |> @orderby_descending(_.a) |> @thenby(_.b) |> DataFrame
6×2 DataFrame
 Row │ a      b     
     │ Int64  Int64 
─────┼──────────────
   1 │     3      2
   2 │     2      1
   3 │     2      2
   4 │     1      1
   5 │     1      2
   6 │     1      3

@groupjoin コマンド

outer |> @groupjoin(inner, outer_selector, inner_selector, result_selector)
outer,inner はクエリーできるものなら何でもよい

julia> df1 = DataFrame(a=[1,2,3], b=[1.,2.,3.])
3×2 DataFrame
 Row │ a      b       
     │ Int64  Float64 
─────┼────────────────
   1 │     1      1.0
   2 │     2      2.0
   3 │     3      3.0

julia> df2 = DataFrame(c=[2,4,2], d=["John", "Jim","Sally"])
3×2 DataFrame
 Row │ c      d      
     │ Int64  String 
─────┼───────────────
   1 │     2  John
   2 │     4  Jim
   3 │     2  Sally

julia> x = df1 |> @groupjoin(df2, _.a, _.c, {t1=_.a, t2=length(__)}) |> DataFrame
3×2 DataFrame
 Row │ t1     t2    
     │ Int64  Int64 
─────┼──────────────
   1 │     1      0
   2 │     2      2
   3 │     3      0

@join コマンド

julia> df1 = DataFrame(a=[1,2,3], b=[1.,2.,3.])
3×2 DataFrame
 Row │ a      b       
     │ Int64  Float64 
─────┼────────────────
   1 │     1      1.0
   2 │     2      2.0
   3 │     3      3.0

julia> df2 = DataFrame(c=[2,4,2], d=["John", "Jim","Sally"])
3×2 DataFrame
 Row │ c      d      
     │ Int64  String 
─────┼───────────────
   1 │     2  John
   2 │     4  Jim
   3 │     2  Sally

julia> x = df1 |> @join(df2, _.a, _.c, {_.a, _.b, __.c, __.d}) |> DataFrame
2×4 DataFrame
 Row │ a      b        c      d      
     │ Int64  Float64  Int64  String 
─────┼───────────────────────────────
   1 │     2      2.0      2  John
   2 │     2      2.0      2  Sally

@mapmany コマンド

julia> source = Dict(:a=>[1,2,3], :b=>[4,5])
Dict{Symbol,Array{Int64,1}} with 2 entries:
  :a => [1, 2, 3]
  :b => [4, 5]

julia> q = source |> @mapmany(_.second, {Key=_.first, Value=__}) |> DataFrame
5×2 DataFrame
 Row │ Key     Value 
     │ Symbol  Int64 
─────┼───────────────
   1 │ a           1
   2 │ a           2
   3 │ a           3
   4 │ b           4
   5 │ b           5

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia でクエリー(概観)

2021年02月01日 | ブログラミング

julia> using Query, DataFrames

説明のために使うデータフレーム

julia> df = DataFrame(name=["John", "Sally", "Kirk"],
                     
age=[23., 42., 59.], children=[3,5,2])
3×3 DataFrame
 Row │ name    age      children 
     │ String  Float64  Int64    
─────┼───────────────────────────
   1 │ John       23.0         3
   2 │ Sally      42.0         5
   3 │ Kirk       59.0         2

スタンドアローンのクエリー演算子

q = df |> @query(i, begin ... end) |> DataFrame

df を対象として,@filter で age>50 を取り出し,@map で name と children を取り出し,DataFrame 型にして,x に代入する。
|> はパイプ演算子
_.age>50 は i->i.age>50 の省略形

julia> x = df |>
         @filter(_.age>50) |>
         @map({_.name, _.children}) |>
         DataFrame

julia> println(x)
1×2 DataFrame
 Row │ name    children 
     │ String  Int64    
─────┼──────────────────
   1 │ Kirk           2

LINQ スタイルのクエリー

q = @from <range variable> in <source> begin
    <query statements>
end

julia> x = @from i in df begin
           @where i.age>50
           @select {i.name, i.children} # NamedTuple を構成する
           @collect DataFrame # DataFrame にする
       end
1×2 DataFrame
 Row │ name    children 
     │ String  Int64    
─────┼──────────────────
   1 │ Kirk           2

julia> println(x)
1×2 DataFrame
 Row │ name    children 
     │ String  Int64    
─────┼──────────────────
   1 │ Kirk           2

LNQ スタイルのクエリーをパイプに組み込むこともできる

q = df |> @query(i, begin ... end) |> DataFrame

julia> x = df |> @query(i, begin
                   @where i.age>50
                   @select {i.name, i.children}
                 end) |> DataFrame
1×2 DataFrame
 Row │ name    children 
     │ String  Int64    
─────┼──────────────────
   1 │ Kirk           2

julia> println(x)
1×2 DataFrame
 Row │ name    children 
     │ String  Int64    
─────┼──────────────────
   1 │ Kirk           2

 

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

PVアクセスランキング にほんブログ村

PVアクセスランキング にほんブログ村