4

F#で計算を実行するために、csvファイルのエントリにアクセスするにはどうすればよいですか?

通常の方法でcsvファイルをメモリに読み込むことができますが、そこでスタックします。

理想的には、列から配列を作成し、array.map2を使用して計算を実行します。

したがって、配列1はWebサイトの使用状況の指標であり、列2は列1の値に達したユーザーの数です(たとえば、Webサイトに6回アクセスした場合)。配列内の各エントリに乗算することで、平均訪問数を計算できます。列1、列2から作成され、列2のarray.sumで除算された配列。

F#スニペットhttp://fssnip.net/3Tでcsv to Arrayコードを試しましたが、一連の文字列タプルである配列が生成されます。

誰かがより良いアプローチを提案できますか?

編集:いくつかのサンプル入力はこれに似ています:-

     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;}; ...]

これは計算にはあまり役立ちません...

4

3 に答える 3

6

私がやっていることは、後で強く型付けされた操作を使用できるようにレコードタイプを作成し、次に次の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
于 2012-10-23T10:49:25.367 に答える
6

F#3.0タイプのプロバイダーを使用すると、CSVファイルへのアクセスがはるかに簡単になることを追加する価値があります。型プロバイダーは、コンパイル中にCSVデータを静的に調べ、列を表す型を生成して(などBookWindow)、個々の列のデータ型を推測できます。

たとえば、新しいバージョンのTry F#Webサイトの「FinancialModeling」の下にある「Using the YahooFinanceTypeProvider」の記事を参照してください。次のように書くことができます:

#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サンプルパックに含まれています。GitHubリポジトリで型推論も処理するより良いバージョンがあります。

データをメモリに保存したら、標準のF#関数を使用して計算を実行できます。たとえば、平均終値を計算するには(Try F#で試すことができます)、次のように記述できます。

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

これにより、終値だけのリストが生成され、数値の標準平均関数が呼び出されます。

于 2012-10-23T13:31:16.213 に答える
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
于 2012-10-23T10:13:56.790 に答える