在任何csv文件上使用CSVprovider时,我使用了以下内容:
http://spatialkeydocs.s3.amazonaws.com/FL_insurance_sample.csv.zip
type statsProvider = CsvProvider<"../../FL_insurance_sample.csv",",">
let stats = statsProvider.Load("../../FL_insurance_sample.csv")
let firstRow = stats.Rows |> Seq.head
CSVProvider仅返回第一列中的数据。它确实正确地标识了列(18)和列的名称,但是当你查看行的类型时,它们只是键入字符串,而不是元组或结构...
在屏幕截图中看到firstRow的类型应该是特定类型,例如元组或结构不是字符串。
我做错了什么?使用Visual Studio 2017,FSharp 4.1,.net 4.5.2和FSharp.Data 2.3.3
注意:至少还有3个csv文件会发生这种情况。我选择这个特殊的csv仅用于演示。
答案 0 :(得分:1)
我无法重现您的问题:您提供的示例CSV文件对我来说效果很好。但是,我使用的是VS Code,而不是Visual Studio;问题的根源可能是Visual Studio 2017中的某个位置,而不是FSharp.Data中的某个位置。这是我做的:
.paket/paket.bootstrapper.exe
。paket init
。paket.dependencies
文件以添加FSharp.Data
。paket install
。paket generate-load-scripts
,它在.paket/load
文件夹中创建了一堆脚本,一次加载所有依赖项。 (我喜欢这个功能用于编写脚本!)使用以下内容创建script.fsx
:
#load ".paket/load/net452/FSharp.Data.fsx"
open FSharp.Data
type Csv = CsvProvider<"/home/rmunn/Downloads/tmp/csv/FL_insurance_sample.csv">
let data = Csv.GetSample()
printfn "%A" data.Headers
let firstRow = data.Rows |> Seq.head
printfn "%A" firstRow
在VS Code中,选择整个脚本文件并按Alt + Enter将其发送到F#Interactive窗口。
这是我得到的输出:
F# Interactive for F# 4.1
Freely distributed under the Apache 2.0 Open Source License
For help type #help;;
> # silentCd @"/home/rmunn/code/fsharp/tmp/foo";;
- # 1 @"/home/rmunn/code/fsharp/tmp/foo/script.fsx"
- ;;
(snip the copy of my script that F# Interactive echoed)
[Loading /home/rmunn/code/fsharp/tmp/foo/.paket/load/net452/Zlib.Portable.fsx
Loading /home/rmunn/code/fsharp/tmp/foo/.paket/load/net452/FSharp.Data.fsx]
namespace FSI_0002.Zlib
namespace FSI_0002.FSharp
Some
[|"policyID"; "statecode"; "county"; "eq_site_limit"; "hu_site_limit";
"fl_site_limit"; "fr_site_limit"; "tiv_2011"; "tiv_2012";
"eq_site_deductible"; "hu_site_deductible"; "fl_site_deductible";
"fr_site_deductible"; "point_latitude"; "point_longitude"; "line";
"construction"; "point_granularity"|]
(119736, "FL", "CLAY COUNTY", 498960M, 498960M, 498960M, 498960M, 498960M,
792148.9M, 0M, 9979.2M, 0, 0, 30.102261M, -81.711777M, "Residential", "Masonry",
1)
type Csv = FSharp.Data.CsvProvider<...>
val data : FSharp.Data.CsvProvider<...>
val firstRow : FSharp.Data.CsvProvider<...>.Row =
(119736, "FL", "CLAY COUNTY", 498960M, 498960M, 498960M, 498960M, 498960M,
792148.9M, 0M, 9979.2M, 0, 0, 30.102261M, -81.711777M, "Residential",
"Masonry", 1)
val it : unit = ()
然而,所有人都没有顺利完成 。当我尝试处理每一行时,我得到以下异常:
System.Exception:无法根据模式解析行2439:期望fl_site_deductible中的Int32,得到68817.6
(我省略了回溯,因为知道FSharp.Data中哪个行号抛出该异常对你没有特别帮助。)
可以在CsvProvider documentation的“控制列类型”部分中看到此问题的原因,其中包含:
默认情况下,CSV类型提供程序会检查前1000行以推断类型,但您可以通过指定CsvProvider的InferRows静态参数来自定义它们。如果指定0,则将使用整个文件。
有两种方法可以解决“推断的int但应该是小数”的问题。一种方法是将InferRows=0
添加到CsvProvider
类型定义中。另一种方法是指定一个显式模式,通过仅查看前1000个来告诉CsvProvider哪些行会出错。 (如果您的数据集很大,这是非常可取的,因为查看所有行以推断数据类型将花费太长时间)。有关示例,请参阅文档,但您可以执行Schema="fl_site_deductible=decimal"
。
因此,如果您无法让代码在Visual Studio中运行,请参阅VS Code(使用Ionide-Paket,Ionide-FSharp和Ionide-FAKE扩展)是否适合您。