裏 RjpWiki

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

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でシェアする

数値計算には気をつけよ

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

某所で,以下の数学入試問題を Python で解くというのをやっていたけど,ちょっと雑な扱いだったのでちゃんとやっておく。

元記事では f(x) のグラフを描くだけでお茶を濁しているけど,どうせなら sympy を使えば良いかと思います。

Julia でも SymPy で使えます。

(1) は導関数を求めて x > 0 で 負であることを示せば良いかな。グラフを描くなら導関数のグラフを描こう。外観がつかめたら lim x → 0,lim x  → ∞ でどうなるか limit で示す。

using SymPy
@syms a b f g k w x z

f = (x + 1) * log(1 + 1/x)
g = diff(f) # 導関数

limit(g, x, 0) # -∞
limit(g, x, Inf) # 0

(2) でも,「解く方法としてはいたって簡単です。代入していくだけです。脳筋です。」として,図を描こうとしているのだが,

pow(k+1,k+1)/special.factorial(k)/pow(a,k)

をそのまま使ったものだから下のような図になりまして,

「10~20の間で数字が落ちているようです。今回は最大値を求めろなので問題なさそうです。どうやらk=2,3のときに最大値を取るようです。」としているが,何故「数字が落ちている」のか考察しようともしていないのはちょっとねえ。

exp((k+1)*log(k + 1) - k*log(2^8/ 3^4)- logfactorial(k))

でやらないとダメです。比較するとどうしてダメだったのかわかるでしょう。

julia> using SpecialFunctions, Printf

julia> funcb(k) = (k + 1) ^ (k + 1) / (2^8/ 3^4)^k / factorial(k)
funcb (generic function with 1 method)

julia> funcb2(k) = exp((k+1)*log(k + 1) - k*log(2^8/ 3^4)- logfactorial(k))
funcb2 (generic function with 1 method)

julia> for k = 0:20
               @printf("%2d %20.15f %20.15f\n", k, funcb(k), funcb2(k))
       end

 0    1.000000000000000    1.000000000000000
 1    1.265625000000000    1.265625000000000
 2    1.351524353027344    1.351524353027344
 3    1.351524353027344    1.351524353027344
 4    1.305025489273248    1.305025489273248
 5    1.232967201857537    1.232967201857539
 6    1.147688698458480    1.147688698458479
 7    1.056829030163603    1.056829030163603
 8    0.965211505305653    0.965211505305653
 9    0.875875642792911    0.875875642792914
10    0.790691444309025    0.790691444309024
11    0.710746653906890    0.710746653906893
12    0.636600915295705    0.636600915295703
13    0.568457341240705    0.568457341240706
14    0.506280597184257    0.506280597184257
15    0.000000000000000    0.449879200714691
16   -0.001380880825857    0.398963280942955
17   -0.000004461526006    0.353185192585937
18    0.000001002536991    0.312167985688245
19   -0.000000005521767    0.275525189547352
20   -0.000000000066342    0.242874345836610

なお,「1.351524353027344 が最大値Mのようです(既約分数ではありませんが...)」とあるが,これもJulia の rational で計算すると
(3^3 // (2^8 // 3^4)^2 // 2) # 177147//131072
(4^4 // (2^8 // 3^4)^3 // 2 // 3) # 177147//131072

funcb (generic function with 1 method)
z(2)
1.351524353027344
z(3)
1.351524353027344
 
(3^3 // (2^8 // 3^4)^2 // 2)
177147//131072
float(ans)
1.3515243530273438
(4^4 // (2^8 // 3^4)^3 // 2 // 3)
177147//131072
747/2
373.5
 
 
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

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

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