2014-09-24 32 views
2

我想使用定數在DataFrame上做基於行的過程。但我無法將我的想法調整到Deedle方式。如何做一個基於行的過程使用定定律(框架和框架輸出)

說像

Indicator1 Indicator2 
1 100  200 
2 300  500 
3 -200  1000 

一個Frame說,有一些規則需要被施加到每個指示器:

  1. 如果指標值小於500和大於0時,通過乘以1.1
  2. 如果指標值小於0,使其爲NaN

我一直在嘗試要使用Frame.mapRow ....函數。

我知道我可以使用

fun v -> let indVal = v.GetAs<Int>("Indicator1"); 
     let newIndVal = match indVal with 
         |...... logic 
         |...... some other logic 
     let indVal2 = v.GetAs<Int>("Indicator2"); 
     let newIndVal2 = match indVal2 with 
         |...... logic 
         |...... some other logic 

Frame.mapRow ....

但我在如何使newIndValnewIndVal2卡放回一行,並最終回到一個新的數據框。

我想實現的是一個框架和框架。此外,我只知道逐一處理列(通過索引或名稱檢索後)。如果要應用的邏輯是通用的,有沒有辦法將邏輯應用於一列一列?

一個必要(和非常簡單的)方式使用C或C#二維數組做,這是

loop through the row dimension 
    loop through the column dimension 
     apply the rule as the side effect to the array[row,col] 

如何Deedle實現這一目標?

UPDATE:如果計算並不需要從同一行中引用其他列

葉花環的建議的偉大工程。對於我的情況,我需要逐行查看數據,因此我想使用Frame.mapRows。我本來應該清晰的簡化規定:

說一幀像

Indicator1 Indicator2 
1 100  200 
2 <Missing> 500 
3 -200  1000 
4 100  <Missing> 
5 <Missing> 500 
6 -200  100 

例如 如果INDICATOR1小於300,新INDICATOR2值INDICATOR2 + 5%* INDICATOR1

我需要使用

mapRows fun k v -> let var1 = v.get("Indicator1") 
        let var2 = v.get("Indicator2") 
        run through the conditions and produce new var1 and var2 
        produce a objectSeries 
|> Frame.ofRows 

上述04-0030-03代碼聽起來很簡單,但我不能想出如何重現適當objectSeriesŧ o重新創建框架。

我也發現了一些我不能mapRows函數[SO問題]解釋:Deedle Frame.mapRows how to properly use it and how to construct objectseries properly

更新

由於原來的問題被張貼,我因爲所使用Deedle在C#。令我驚訝的是,基於行的計算在C#中非常容易,C#Frame.rows函數處理缺失值的方式與F#mapRows函數非常不同。以下是我用來嘗試真正邏輯的一個非常基本的例子。它可能是任何人誰是尋找類似的應用程序非常有用:

事情要注意是: 1.行功能沒有,而兩列價值缺失 2.平均函數刪除行智能足以根據可用數據點計算平均值。

using System.Text; 
using System.Threading.Tasks; 
using Deedle; 

namespace TestDeedleRowProcessWithMissingValues 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var s1 = new SeriesBuilder<DateTime, double>(){ 
       {DateTime.Today.Date.AddDays(-5),10.0}, 
       {DateTime.Today.Date.AddDays(-4),9.0}, 
       {DateTime.Today.Date.AddDays(-3),8.0}, 
       {DateTime.Today.Date.AddDays(-2),double.NaN}, 
       {DateTime.Today.Date.AddDays(-1),6.0}, 
       {DateTime.Today.Date.AddDays(-0),5.0} 
      }.Series; 

      var s2 = new SeriesBuilder<DateTime, double>(){ 
       {DateTime.Today.Date.AddDays(-5),10.0}, 
       {DateTime.Today.Date.AddDays(-4),double.NaN}, 
       {DateTime.Today.Date.AddDays(-3),8.0}, 
       {DateTime.Today.Date.AddDays(-2),double.NaN}, 
       {DateTime.Today.Date.AddDays(-1),6.0}     
      }.Series; 

      var f = Frame.FromColumns(new KeyValuePair<string, Series<DateTime, double>>[] { 
       KeyValue.Create("s1",s1), 
       KeyValue.Create("s2",s2) 
      }); 

      s1.Print(); 
      f.Print(); 


      f.Rows.Select(kvp => kvp.Value).Print(); 

//   29/05/2015 12:00:00 AM -> series [ s1 => 10; s2 => 10] 
//   30/05/2015 12:00:00 AM -> series [ s1 => 9; s2 => <missing>] 
//   31/05/2015 12:00:00 AM -> series [ s1 => 8; s2 => 8] 
//   1/06/2015 12:00:00 AM -> series [ s1 => <missing>; s2 => <missing>] 
//   2/06/2015 12:00:00 AM -> series [ s1 => 6; s2 => 6] 
//   3/06/2015 12:00:00 AM -> series [ s1 => 5; s2 => <missing>] 


      f.Rows.Select(kvp => kvp.Value.As<double>().Mean()).Print(); 

//   29/05/2015 12:00:00 AM -> 10 
//   30/05/2015 12:00:00 AM -> 9 
//   31/05/2015 12:00:00 AM -> 8 
//   1/06/2015 12:00:00 AM -> <missing> 
//   2/06/2015 12:00:00 AM -> 6 
//   3/06/2015 12:00:00 AM -> 5 


      //Console.ReadLine(); 
     } 
    } 
} 

回答

2

您可以使用Frame.mapValues映射幀中的所有值。爲它提供一個可以獲取數據類型並返回更新值的函數。

let indicator1 = [100.0;300.0;-200.0] |> Series.ofValues 
let indicator2 = [200.0;500.0;1000.0] |> Series.ofValues 

let frame = Frame.ofColumns ["indicator1" => indicator1; "indicator2" => indicator2] 
// val frame : Frame<int,string> = 
// 
//  indicator1 indicator2 
// 0 -> 100  200  
// 1 -> 300  500  
// 2 -> -200  1000  

let update v = 
    match v with 
    |v when v<500.0 && v>0.0 -> v * 1.1 
    |v when v<0.0 -> nan 
    |v -> v 

let newFrame = frame |> Frame.mapValues update 
// val newFrame : Frame<int,string> = 
// 
//  indicator1 indicator2 
// 0 -> 110  220  
// 1 -> 330  500  
// 2 -> <missing> 1000 
+0

'Frame.mapValues'在ObersevationSeries中傳遞到函數參數中。像提議的更新函數這樣的重構函數必須在函數參數中調用(而不是上面所示)。而我的問題是我沒有一個elegent的方式來重新創建觀察系列並重新創建dataFrame。 Frame.mapValues不返回一個Frame。 – casbby 2014-09-24 21:43:48

+0

對不起,我沒有完全理解你的評論,但是'Frame.mapValues'確實返回了一個'Frame'。請參閱[源代碼](https://github.com/BlueMountainCapital/Deedle/blob/c730ec005b4632e3300438338cad445bef9c0b4e/src/Deedle/FrameModule.fs#L1096)。 – 2014-09-25 08:27:44

+0

不幸的是Frame.mapValues和Frame.mapColumns函數適用於我。我需要使用Frame.mapRows forumla。我在這個問題中給出的例子可能太簡單了。計算邏輯需要引用同一行中的其他列。一個更接近的例子是[link](http://stackoverflow.com/questions/26016793/f-bootstrap-a-sequence-of-value-using-recursion-should-deedle-be-used-for-such )。 – casbby 2014-09-25 22:31:08

相關問題