将 JSON 扩展到 deedle 数据框的列
Expanding JSON to columns of a deedle dataframe
我正在尝试将从网站获取的 JSON 转换为 deedle 数据框,将 JSON 条目扩展为数据框的单独列。我找到 this discussion,但我无法使建议的解决方案对我有用。由于我对 JSON 和 deedle 都不熟悉,所以我可能犯了一个愚蠢的错误。我正在尝试以下操作(大部分是从引用的讨论中复制的):
let rec expander key value =
seq {
match value with
| JsonValue.String (s) -> yield key,typeof<string>,box s
| JsonValue.Boolean (b) -> yield key,typeof<bool>,box b
| JsonValue.Float (f) -> yield key,typeof<float>,box f
| JsonValue.Null (_) -> yield key,typeof<obj>,box ()
| JsonValue.Number (n) -> yield key,typeof<decimal>,box n
| JsonValue.Record (r) -> yield! r |> Seq.collect ((<||)expander)
| JsonValue.Array (a) ->
yield! a
|> Seq.collect (expander "arrayItem")
}
Frame.CustomExpanders.Add(typeof<JsonDocument>,
fun o -> (o :?> JsonDocument).JsonValue |> expander "root")
Frame.CustomExpanders.Add(typeof<JsonValue>,
fun o -> o :?> JsonValue |> expander "root")
let info =
JsonValue.Parse(""" { "name": "Tomas", "born": 1985 } """)
let df =
[ series ["It" => info] ]
|> Frame.ofRowsOrdinal
let dfexpanded = Frame.expandAllCols 2 df
这给了我一些我不知道如何解释的东西,但不是我想要的结果:
It.properties It.Tag It.IsString It.IsNumber It.IsFloat It.IsRecord It.IsArray It.IsBoolean It.IsNull It._Print
0 -> System.Tuple`2[System.String,FSharp.Data.JsonValue][] 3 False False False True False False False { "name": "Tomas", "born": 1985 }
非常感谢您的意见!
问题似乎是数据框中It
的类型不是JsonValue
,而是编译器生成的代表个体的子class之一可区分联合的情况 - 在这种特殊情况下,一个名为 JsonValue+Record
.
的嵌套类型
Deedle 会寻找精确的类型匹配(并且不会尝试为基础 class 寻找扩展器),因此解决方法是为每个嵌套的 class:[=15= 注册扩展器]
for t in typeof<JsonValue>.GetNestedTypes() do
Frame.CustomExpanders.Add(t, fun o -> o :?> JsonValue |> expander "root")
在 运行 之后,您的代码给出了预期的结果:
val dfexpanded : Frame<int,string> =
It.name It.born
0 -> Tomas 1985
我正在尝试将从网站获取的 JSON 转换为 deedle 数据框,将 JSON 条目扩展为数据框的单独列。我找到 this discussion,但我无法使建议的解决方案对我有用。由于我对 JSON 和 deedle 都不熟悉,所以我可能犯了一个愚蠢的错误。我正在尝试以下操作(大部分是从引用的讨论中复制的):
let rec expander key value =
seq {
match value with
| JsonValue.String (s) -> yield key,typeof<string>,box s
| JsonValue.Boolean (b) -> yield key,typeof<bool>,box b
| JsonValue.Float (f) -> yield key,typeof<float>,box f
| JsonValue.Null (_) -> yield key,typeof<obj>,box ()
| JsonValue.Number (n) -> yield key,typeof<decimal>,box n
| JsonValue.Record (r) -> yield! r |> Seq.collect ((<||)expander)
| JsonValue.Array (a) ->
yield! a
|> Seq.collect (expander "arrayItem")
}
Frame.CustomExpanders.Add(typeof<JsonDocument>,
fun o -> (o :?> JsonDocument).JsonValue |> expander "root")
Frame.CustomExpanders.Add(typeof<JsonValue>,
fun o -> o :?> JsonValue |> expander "root")
let info =
JsonValue.Parse(""" { "name": "Tomas", "born": 1985 } """)
let df =
[ series ["It" => info] ]
|> Frame.ofRowsOrdinal
let dfexpanded = Frame.expandAllCols 2 df
这给了我一些我不知道如何解释的东西,但不是我想要的结果:
It.properties It.Tag It.IsString It.IsNumber It.IsFloat It.IsRecord It.IsArray It.IsBoolean It.IsNull It._Print
0 -> System.Tuple`2[System.String,FSharp.Data.JsonValue][] 3 False False False True False False False { "name": "Tomas", "born": 1985 }
非常感谢您的意见!
问题似乎是数据框中It
的类型不是JsonValue
,而是编译器生成的代表个体的子class之一可区分联合的情况 - 在这种特殊情况下,一个名为 JsonValue+Record
.
Deedle 会寻找精确的类型匹配(并且不会尝试为基础 class 寻找扩展器),因此解决方法是为每个嵌套的 class:[=15= 注册扩展器]
for t in typeof<JsonValue>.GetNestedTypes() do
Frame.CustomExpanders.Add(t, fun o -> o :?> JsonValue |> expander "root")
在 运行 之后,您的代码给出了预期的结果:
val dfexpanded : Frame<int,string> =
It.name It.born
0 -> Tomas 1985