在 F# 中使用 CsvProvider

Posted

技术标签:

【中文标题】在 F# 中使用 CsvProvider【英文标题】:using CsvProvider in F# 【发布时间】:2016-04-10 07:37:13 【问题描述】:

我是 F# 的初学者,我正在尝试使用 CsvProvider 并重现此处给出的示例

http://fsharp.github.io/FSharp.Data/library/CsvProvider.html

所以在 F# 交互中,我输入

>type Stocks = CsvProvider<"MSFT.csv">;;

type Stocks = CsvProvider<...>

> let msft = CsvProvider<"MSFT.csv">.GetSample();;

val msft : CsvProvider<...>

> msft;;
val it : CsvProvider<...> =
  FSharp.Data.Runtime.CsvFile`1[System.Tuple`1[System.String]]

    Headers = Some [|"MSFT.csv"|];
 NumberOfColumns = 1;
 Quote = '"';
 Rows = seq [];
 Separators = ",";

> let firstRow = msft.Rows |> Seq.head;;
System.ArgumentException: The input sequence was empty.
Parameter name: source
>    at Microsoft.FSharp.Collections.SeqModule.Head[T](IEnumerable`1 source)
   at <StartupCode$FSI_0044>.$FSI_0044.main@()
Stopped due to error

我的理解是 CsvProvider 基于 CSV 文件创建一个类型,这样以后就可以读取该文件或具有相同格式的不同文件/流。 我认为我没有目录问题,因为如果文件位于错误的目录中,该函数将返回错误。 创建 msft 时,F# 显示 NumberOfColumns= 1 但这显然是错误的。

这也不行

> let msft = Stocks.Parse("MSFT.csv");;

val msft : CsvProvider<...>

> msft;;
val it : CsvProvider<...> =
  FSharp.Data.Runtime.CsvFile`1[System.Tuple`1[System.String]]
    Headers = Some [|"MSFT.csv"|];
     NumberOfColumns = 1;
     Quote = '"';
     Rows = seq [];
     Separators = ",";

我正在使用这样的 FSharp.Data 库:(它是好版本吗?)

>#r "C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Algo Stanford I\packages\FSharp.Data.2.2.5\lib\portable-net40+sl5+wp8+win8\FSharp.Data.dll"
--> Referenced 'C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Algo Stanford I\packages\FSharp.Data.2.2.5\lib\portable-net40+sl5+wp8+win8\FSharp.Data.dll'
> open FSharp.Data;;
> 

请帮忙!!!我已经尝试了几个小时了!谢谢!!!

EDIT:以下是 F# interactive 的完整日志

Microsoft (R) F# Interactive version 14.0.23020.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> #r "C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Algo Stanford I\packages\FSharp.Data.2.2.5\lib\portable-net40+sl5+wp8+win8\FSharp.Data.dll"
open FSharp.Data;;

--> Referenced 'C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Algo Stanford I\packages\FSharp.Data.2.2.5\lib\portable-net40+sl5+wp8+win8\FSharp.Data.dll'

> open FSharp.Data;;
> #I "C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Algo Stanford I";;

--> Added 'C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Algo Stanford I' to library include path

> let msft = CsvProvider<"MSFT.csv">.GetSample();;

val msft : CsvProvider<...>

> msft;;
val it : CsvProvider<...> =
  FSharp.Data.Runtime.CsvFile`1[System.Tuple`1[System.String]]
    Headers = Some [|"MSFT.csv"|];
     NumberOfColumns = 1;
     Quote = '"';
     Rows = seq [];
     Separators = ",";
> let msft = CsvProvider<"C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Algo Stanford I\MSFT.csv">.GetSample();;

  let msft = CsvProvider<"C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Algo Stanford I\MSFT.csv">.GetSample();;
  ---------------------------------------------------------------------------------------------------^^^^^^^^^

stdin(7,100): error FS0039: The field, constructor or member 'GetSample' is not defined
> let msft = CsvProvider<"MSFT.csv">.GetSample();;

val msft : CsvProvider<...>

> let msft = CsvProvider<"C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Algo Stanford I\MSFT.csv">.GetSample();;

  let msft = CsvProvider<"C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Algo Stanford I\MSFT.csv">.GetSample();;
  ---------------------------------------------------------------------------------------------------^^^^^^^^^

stdin(9,100): error FS0039: The field, constructor or member 'GetSample' is not defined
> 

【问题讨论】:

CSV 文件的内容是什么? (我怀疑它是空的) 它与您可以在我放置的 http 链接上找到的文件相同。它是一个 321ko 文件。这是前 2 行 Date,Open,High,Low,Close,Volume,Adj Close 2012-01-27,29.45,29.53,29.17,29.23,44187700,29.23 2012-01-26,29.61,29.70,29.40,29.50 ,49102800,29.50 我无法重现此问题。当您下载文件时,如果您在 Windows 上,您是否确保打开文件的属性并取消阻止它?出于安全原因,从 Internet 下载的文件通常会被“锁定”,这也可能会影响 CSV 提供程序。 我确实在 Windows 上,但文件没有被阻止。我对其他文件也有同样的问题。我可以毫无问题地在写字板中打开它们。 【参考方案1】:

我的猜测是 F# Interactive 很难在当前目录中找到 MSFT.csv 文件。您可以使用Literal 指定相对于当前目录的完整路径:

let [<Literal>] Sample = __SOURCE_DIRECTORY__ + "\\MSFT.csv"
type Stocks = CsvProvider<Sample>

然后就可以调用Stocks.GetSample()读取文件了。

这种错误有时会在 F# Interactive 中发生,尤其是当您在不同文件夹中的文件之间切换时(我认为 F# Interactive 会记住上次执行命令的文件夹,但我认为它的行为并不总是像预期的那样)。

【讨论】:

为清楚起见,我在 F# 交互中复制/粘贴了整个会话 输入完整路径时,需要对反斜杠进行转义。你可以写CsvProvider&lt; @"C:\foo.csv" &gt;CsvProvider&lt;"C:\\foo.csv"&gt; &gt; let msft = CsvProvider&lt;"C:\\Users\Fagui\Documents\GitHub\Learning Fsharp\Algo Stanford I\MSFT.csv"&gt;.GetSample();; let msft = CsvProvider&lt;"C:\\Users\Fagui\Documents\GitHub\Learning Fsharp\Algo Stanford I\MSFT.csv"&gt;.GetSample();; ----------------------------------------------------------------------------------------------------^^^^^^^^^ stdin(11,101): error FS0039: The field, constructor or member 'GetSample' is not defined &gt; let msft = CsvProvider&lt;@"C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Algo Stanford I\MSFT.csv"&gt;.GetSample();; ---------------------------------------------------------------------------------------------------------------^^ stdin(12,112): error FS0010: Incomplete structured construct at or before this point in quotation literal. Expected end of quotation or other token. @ 符号前需要一个空格 - CsvProvider&lt; @"...." &gt;。这有点傻,但它是 F# 解析器工作原理的产物。

以上是关于在 F# 中使用 CsvProvider的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中定义 F# '**' 运算符

在 F# 中使用机器学习的资源 [关闭]

在多个表中使用count(decode ...)

在 Python 中使用 %f 和 strftime() 来获得微秒

F# 在同一项目的另一个文件中定义/使用类型/模块

在 Rails 中使用“f.input 集合”的 onChange 方法