中高年のF#

プログラミング言語F#を学ぶ。Foundations of F#とExpert F#は、ある程度読んだ。オブジェクト指向は決して使わないと決意している。

mergeOnForeignKeyColumnの欠点をどう回避するか

自作したmergeOnForeignKeyColumnには、転記したカラムのデータ型がすべてobjになってしまうという欠点がある。Deedleのソースを読んで調べてみたが、どうすればこの欠点を直せるのかは分からなかった。

しかし回避する方法はある。一つは、mergeOnForeignKeyColumnの実行後に、カラムのデータ型を設定する方法だ。具体的には、


xx.ReplaceColumn("a", xx.GetColumn<string>("a"))



を実行すればxxの値であるフレームのカラムaのデータ型はobjではなくstringになる。これを繰り返せば、すべてのカラムについてデータ型を設定できる。

もう一つの方法は、一つのカラムだけを転記する関数を設け、その型引数によってカラムのデータ型を指定することだ。この関数を繰り返し実行すれば、すべてのカラムを正しいデータ型で転記できる。具体的には、

mergeColumnFromFrameOnForeignKeyColumn<string,_,_,_>  "a"  sf "fi" fr1


は、フレームfr1のカラムfiがforeign keyになっているので、このforeign keyを利用してフレームsfの列を参照し、カラムaからデータ型がstringである値を転記せよという意味だ。データ型がobjではなくstringになっていること、mergeColumnFromFrameOnForeignKeyColumnの最初の型引数でstringと指定されていることに注意。

性能を調べてみると、後者の方がずっと速い。前者はbox/unboxが繰り返し呼ばれているが、後者はその必要がないからだと推測する。

let mergeColumnFromFrameOnForeignKeyColumn<'X, 'C, 'R1, 'R2 
when 'X : null and 'C: equality and 'R1: equality and 'R2: equality>
(column_to_be_copied: 'C) (indexed_frame: Frame<'R2,'C>)
(key_column: 'C) (primary_frame: Frame<'R1,'C>) =
let srs_references: Series<'R1, 'R2> =
primary_frame |> getCol key_column

let (srs_cols_to_be_merged: Series<_,'X>) =
getCol column_to_be_copied indexed_frame
let new_srs =
srs_references
|> Series.mapValues
(fun x -> if srs_cols_to_be_merged.ContainsKey(x) then
srs_cols_to_be_merged.[x]
else null)
addCol column_to_be_copied new_srs primary_frame

Deedleでデータサイエンス100本ノック(17)

これで一応完了した。読み返して確定稿とするつもり。

#96

let p096() = 
use stringWriter = new System.IO.StringWriter()
df_product_full.SaveCsv(stringWriter, includeRowKeys=false)
stringWriter.Close()
use stringReader = new System.IO.StringReader(stringWriter.ToString())
use finalStreamWriter = new System.IO.StreamWriter(new FileStream("h:/home/makoto/100knocks-preprocess/docker/work/data/product_full96Rev.csv", FileMode.Create), Text.Encoding.UTF8)
stringReader.ReadLine() |> ignore
while stringReader.Peek() <> -1 do
finalStreamWriter.WriteLine(stringReader.ReadLine())



#97

Frame.ReadCsv ("h:/home/makoto/100knocks-preprocess/docker/work/data/product_full94.csv", true, true)
|> take 10


#98

Frame.ReadCsv ("h:/home/makoto/100knocks-preprocess/docker/work/data/product_full96Rev.csv", false)
|> take 10


#99

df_product_full.SaveCsv("h:/home/makoto/100knocks-preprocess/docker/work/data/product_full99.tsv", includeRowKeys=false)


#100

Frame.ReadCsv ("h:/home/makoto/100knocks-preprocess/docker/work/data/product_full99.tsv", separators="\t")
|> take 10

Deedleでデータサイエンス100本ノック(16)


#92

let df_customer_s =
df_customer
|> Frame.dropCol "gender"

let df_gender =
[series [ "gnder_cd" => box 0; "gender" => box "男性"];
series [ "gnder_cd" => box 1; "gender" => box "女性"];
series [ "gnder_cd" => box 9; "gender" => box "不明"]]
|> Frame.ofRowsOrdinal


#93

let df_product_full =
let df_category_indexed_by_small_cd =
df_category
|> Frame.indexRowsInt "category_small_cd"
df_product
|> ((df_product.GetColumnlt;int> "category_small_cd"
|> Series.mapValues (fun small_cd -> (df_category_indexed_by_small_cd.GetColumnlt;string> "category_major_name").[small_cd]))
|> addCol "category_major_name")

|> ((df_product.GetColumnlt;int> "category_small_cd"
|> Series.mapValues (fun small_cd -> (df_category_indexed_by_small_cd.GetColumnlt;string> "category_medium_name").[small_cd]))
|> addCol "category_medium_name")

|> ((df_product.GetColumnlt;int> "category_small_cd"
|> Series.mapValues (fun small_cd -> (df_category_indexed_by_small_cd.GetColumnlt;string> "category_small_name").[small_cd]))
|> addCol "category_small_name")


#94

df_product_full.SaveCsv(
"h:/home/makoto/100knocks-preprocess/docker/work/data/product_full94.csv",
includeRowKeys=true)


#95

open System.IO
let os = new FileStream(
"h:/home/makoto/100knocks-preprocess/docker/work/data/product_full95.csv",
FileMode.Create)
let tw = new StreamWriter(os, Text.Encoding.GetEncoding(932))
df_product_full.SaveCsv(tw, includeRowKeys=true)
tw.Close()
os.Close()

プロフィール

masaito5

オリンピック応援パーク
livedoor × FLO:Q
QRコード
QRコード
  • ライブドアブログ