2012-10-23 52 views
4

如何访问csv文件中的条目以便在F#中对它们执行计算?访问csv文件中的条目以进行计算F#

我可以用通常的方式将csv文件读入内存,但是一旦出现卡住的现象。

理想情况下,我只是从列中创建数组,然后使用array.map2来执行计算。

因此,我的数组1是一些网站使用率指标,第2列是达到第1列中的值的用户数量(说6次访问网站),我们可以通过乘以每个条目来计算平均访问次数在列1的数组中,由第2列构成的数组除以第2列的array.sum。

我已经尝试过csv到F#代码片段上的数组代码,但它为我生成和排列这是一系列字符串元组。

任何人都可以提出一个更好的办法?

编辑:一些样本输入将与此类似: -

 Visits Count 
    1 8 
    2 9 
    3 5 
    4 3 
    5 2 
    6 1 
    7 1 
    10 1 

和输出将返回数据的平均值,在这种情况下,2.87(2位小数)。

编辑2:从CSV到阵列码我发现的电流输出是这

 val it : seq<BookWindow> = 
      seq [{Visits = 1; 
        Count = 8;}; {Visits = 2; 
          Count = 9;}; {Visits = 3; 
            Count = 5;}; {Visits = 4; 
               Count = 3;}; ...] 

这是不是计算如此有用...

+0

您可以添加样本输入和输出吗?为了一个特定的目的,你不需要使用复杂的技术作为你提到的代码片段。 – pad

+0

是的,我认为我是过于复杂的东西! :) –

+0

只有一些OCD踢在CSV中有逗号 - 因此名称。 TSV有标签:-) – Adrian

回答

6

我要做的就是创建一个记录类型,所以我可以使用强类型的操作lateron,然后读取文本文件为seq<myRecord>很快像下面这段代码。如果我打算稍后再次使用,我通常会将该方法移至记录中作为static member fromFile。如果您像我通常那样使用大型文本文件,seq非常有用,它以这种方式使用很少的内存。

编辑这是清洁:

open System.IO 

type myRecord = { 
    Visits: int 
    Count: int 
} with 
    static member fromFile file = 
     file 
     |> File.ReadLines  // expose as seq<string> 
     |> Seq.skip 1   // skip headers 
     |> Seq.map (fun s-> s.Split '\t') // split each line into array 
     |> Seq.map (fun a -> {Visits=int a.[0]; Count=int a.[1]}) // and create record 

myRecord.fromFile @"D:\data.csv" 
|> Seq.fold (fun (tv, tc) r -> (tv+r.Visits*r.Count, tc+r.Count))(0,0) 
|> (fun t -> float (fst t)/float (snd t)) 
//val mean : float = 2.866666667 
+0

辉煌,欢呼。这非常简单,非常有帮助。 –

+1

对不起,错过了关于平均值的位,更新 – gjvdkamp

+0

不用担心!一旦我可以访问条目,获得平均值是没有问题的:) –

2

你可能是过于复杂的东西,这不是最干净的解决方案,但您仍然可以使用您的产品。将BookWindow类型映射为单独的数组,如果这提供了一种很好的方法来执行计算。

type BookWindow = { Visits: int 
        Count: int } 
// Sample data 
let list = [|{Visits = 1; Count = 8;}; {Visits = 2; Count = 9;}; {Visits = 3; Count = 5;}|] 

let visitcol = list |> Array.map (fun r -> r.Visits) 
let countcol = list |> Array.map (fun r -> r.Count) 
Array.map2(fun v c -> v * c) visitcol countcol 
+0

好的,谢谢。你知道一个更简单的解决方案来阅读和访问F#中的csv条目吗?可能只是一个基本的教程会做,我有点挣扎。 –

6

值得一补充说,与F#3.0型提供商,访问的CSV文件是越来越简单了很多。类型提供者可以在编译期间静态查看CSV数据,并生成表示列的类型(如BookWindow),然后推断各个列的数据类型。

例如,看看在“使用雅虎财经类型提供”下“金融建模”文章的new version of Try F# web site。你可以写类似:

#r "Samples.Csv.dll" 

// Type provider that generates schema based on CSV file located online 
[<Literal>] 
let url = "http://ichart.finance.yahoo.com/table.csv?s=MSFT" 
let msft = new Samples.FSharp.CsvProvider.MiniCsv<url>() 

// The provider automatically infers the structure and we 
// can access columns as properties of the 'row' object 
for row in msft.Data do 
    printfn "%A %f" row.Date row.Close 

据我所知,CSV提供的最近一个公开版本是在F# 3.0 Sample Pack。我有一个可能更好的版本,也处理my GitHub repo上的类型推断。

一旦将数据存储在内存中,就可以使用标准F#函数进行计算。例如,要计算平均收盘价(你可以尝试在尝试F#),你可以这样写:

Seq.average [ for row in msft.Data -> row.Close ] 

这会产生与刚刚闭幕的价格列表,然后调用上的数字标准平均功能。

+0

F#3.0在VS 2012中不是吗?必须有一个关于升级的工作,如果有的话...... –

+2

@SimonHayward是的,F#3.0仅在VS 2012中可用。虽然,您也可以免费获取Express版本:http:// blogs。 msdn.com/b/fsharpteam/archive/2012/09/12/announcing-the-release-of-f-tools-for-visual-studio-express-2012-for-web.aspx –

+0

太棒了,会看看。 –