我需要编写 Deedle FrameData (包括" ID"列和其他" Delta"列,空白条目)到CSV。虽然我可以生成 FrameData 的2D数组,但我无法将其正确写入CSV文件。
module SOQN =
open System
open Deedle
open FSharp.Data
// TestInput.csv
// ID,Alpha,Beta,Gamma
// 1,no,1,hi
// ...
// TestOutput.csv
// ID,Alpha,Beta,Gamma,Delta
// 1,"no","1","hi",""
// ...
let inputCsv = @"D:\TestInput.csv"
let outputCsv = @"D:\TestOutput.csv"
let (df:Frame<obj,string>) = Frame.ReadCsv(inputCsv, hasHeaders=true, inferTypes=false, separators=",", indexCol="ID")
// See http://www.fssnip.net/sj/title/Insert-Deedle-frame-into-Excel
let data4Frame (frame:Frame<_,_>) = frame.GetFrameData()
// See http://www.fssnip.net/sj/title/Insert-Deedle-frame-into-Excel
let boxOptional obj =
match obj with
| Deedle.OptionalValue.Present obj -> box (obj.ToString())
| _ -> box ""
// See http://www.fssnip.net/sj/title/Insert-Deedle-frame-into-Excel
let frameToArray (data:FrameData) =
let transpose (array:'T[,]) =
Array2D.init (array.GetLength(1)) (array.GetLength(0)) (fun i j -> array.[j, i])
data.Columns
|> Seq.map (fun (typ, vctr) -> vctr.ObjectSequence |> Seq.map boxOptional |> Array.ofSeq)
|> array2D
|> transpose
let main =
printfn ""
printfn "Output Deedle FrameData To CSV"
printfn ""
let dff = data4Frame df
let rzlt = frameToArray dff
printfn "rzlt: %A" rzlt
do
use writer = new StreamWriter(outputCsv)
writer.WriteLine("ID,Alpha,Beta,Gamma,Delta")
// writer.WriteLine rzlt
0
[<EntryPoint>]
main
|> ignore
我错过了什么?
答案 0 :(得分:3)
我不会使用FrameData
来执行此操作 - 框架数据主要是内部数据,虽然有一些合法用途,但我认为这对此任务没有意义。
如果您只想在输入CSV中添加空Delta
列,则可以执行以下操作:
let df : Frame<int, _> = Frame.ReadCsv("C:/temp/test-input.csv", indexCol="ID")
df.AddColumn("Delta", [])
df.SaveCsv("C:/temp/test-output.csv", ["ID"])
这几乎可以满足您的所有需求 - 它会写出ID
列和额外的Delta
列。
唯一需要注意的是,它不会在数据周围添加额外的引号。除非您需要在列中转义逗号,否则CSV规范不要求这样做,我也不认为有一种简单的方法可以让Deedle执行此操作。
因此,我认为您必须将自己的写作写入CSV文件。下面显示了如何执行此操作,但它没有正确地转义引号和逗号(这就是为什么你应该使用SaveCsv
,即使它们在不需要时也没有引号:
use writer = new StreamWriter("C:/temp/test-output.csv")
writer.WriteLine("ID,Alpha,Beta,Gamma,Delta")
for key, row in Series.observations df.Rows do
writer.Write(key)
for value in Series.valuesAll row do
writer.Write(",")
writer.Write(sprintf "\"%O\"" (if value.IsSome then value.Value else box ""))
writer.WriteLine()
答案 1 :(得分:1)
您可以从库的source获取写入csv的示例(它在那里使用FrameData
)
添加包装后:
type FrameData with
member frameData.SaveCsv(path:string, ?includeRowKeys, ?keyNames, ?separator, ?culture) =
use writer = new StreamWriter(path)
writeCsv writer (Some path) separator culture includeRowKeys keyNames frameData
你可以这样写:
dff.SaveCsv outputCsv