Deedle Frame.mapRows, как правильно его использовать и как правильно построить серию объектов

Я также заметил кое-что странное в функции Deedle mapRows, которую я не могу объяснить:

let col1 =       Series.ofObservations[1=>10.0;2=>System.Double.NaN;3=>System.Double.NaN;4=>10.0;5=>System.Double.NaN;6=>10.0; ]

let col2 = Series.ofObservations[1=>9.0;2=>5.5;3=>System.Double.NaN;4=>9.0;5=>System.Double.NaN;6=>9.0; ]
let f1 = Frame.ofColumns [ "c1" => col1; "c2" => col2 ]
let f2 = f1 |> Frame.mapRows (fun k r -> r) |> Frame.ofRows
let f3 = f1 |> Frame.mapRows (fun k r -> let x = r.Get("c1"); 
                                          let y = r.Get("c2");  
                                          r) |> Frame.ofRows


val f1 : Frame<int,string> =

      c1        c2        
 1 -> 10        9         
 2 -> <missing> 5.5       
 3 -> <missing> <missing> 
 4 -> 10        9         
 5 -> <missing> <missing> 
 6 -> 10        9         

 val f2 : Frame<int,string> =

      c1        c2        
 1 -> 10        9         
 2 -> <missing> 5.5       
 3 -> <missing> <missing> 
 4 -> 10        9         
 5 -> <missing> <missing> 
 6 -> 10        9         

 val f3 : Frame<int,string> =

      c1        c2        
 1 -> 10        9         
 2 -> <missing> <missing> 
 3 -> <missing> <missing> 
 4 -> 10        9         
 5 -> <missing> <missing> 
 6 -> 10        9         

Как f3 может иметь значение, отличное от f2? все, что я сделал с помощью f3, это чтобы получить значение от obejectseries.

Я пытаюсь использовать эту функцию mapRows, чтобы сделать процесс на основе строк и произвести серию объектов, тогда mapRows может создать новый фрейм с теми же ключами строки. Процесс должен основываться на строках, так как значение столбца должно обновляться на основе его собственного значения и соседнего значения.

Вычисление не может быть выполнено, используя столбец к столбцу напрямую, так как вычисление изменяется на основе значения строки.

Цени любой совет

Обновить

Так как оригинальный вопрос был опубликован, я с тех пор использовал 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();
        }
    }
}

1 ответ

Решение

Причина по которой f3 отличается от того, как mapRows обрабатывает пропущенные значения.

Когда вы получаете доступ к значению с помощью r.Get("C1")вы либо получаете значение, либо вы получаете ValueMissingException, mapRows Функция обрабатывает это исключение и помечает всю строку как отсутствующую. Если вы напишите просто:

let f3 = f1 |> Frame.mapRows (fun k r -> 
  let x = r.Get("c1"); 
  let y = r.Get("c2");  
  r)

Тогда результат будет:

1 -> series [ c1 => 10; c2 => 9] 
2 -> <missing>                   
3 -> <missing>                   
4 -> series [ c1 => 10; c2 => 9] 
5 -> <missing>                   
6 -> series [ c1 => 10; c2 => 9] 

Если вы хотите написать функцию, которая возвращает фрейм как он есть (чтение данных из исходных строк и создание новых строк), вы можете сделать что-то вроде:

f1 
|> Frame.mapRows (fun k r -> 
  [ "X" => OptionalValue.asOption(r.TryGet("c1")); 
    "Y" => OptionalValue.asOption(r.TryGet("c2")) ] 
  |> Series.ofOptionalObservations )
|> Frame.ofRows
Другие вопросы по тегам