Data Frame - согласованность порядка при преобразовании в матрицу

У меня есть дидл Frame<DateTime,string>, Столбцы содержат float значения и являются плотными (без пропущенных значений).

Мне нужно построить фрейм данных из string [] а потом:

  • Построить 2D Matrix со всеми данными
  • Построить серию Series<DateTime,Matrix<float,CpuLib>>, сворачивая ряды в 1xn матрица

В моем случае я экспериментирую с FCore от StatFactory, но в будущем я могу использовать другую библиотеку линейной алгебры.

Меня беспокоит то, что мне нужно убедиться, что порядок строк и столбцов в процессе не изменился.

Построение фрейма данных

Я получаю данные, используя следующее. Я заметил, что порядок столбцов отличается от первоначального списка тикеров. Это почему? Будет ли использование Array.Parallel.Map изменить порядок?

/// get the selected tickers in a DataFrame from a DataContext  
let fetchTickers tickers joinKind =

    let getTicker ticker = 
        query {
            for row in db.PriceBarsDay do
            where (row.Ticker = ticker)
            select row } 
       |> Seq.map (fun row -> row.DateTime, float row.Close)
       |> dict

    tickers
    |> Array.map (fun ticker -> getTicker ticker)  // returns a dict(DateTime, ClosePrice)
    |> Array.map (fun dictionary -> Series(dictionary))
    |> Array.map2 (fun ticker series -> [ticker => series] |> frame ) tickers
    |> Array.reduce (fun accumFrame frame -> accumFrame.Join(frame, joinKind))

Кадр данных в 2D матрицу

Для построения матрицы я использую код ниже. Отображение на массив имен столбцов (selectedCols) гарантирует, что порядок столбцов не смещается. Я запускаю модульные тесты в порядке строк, используя Array.Map и все выглядит хорошо, но я хотел бы знать,

  • если в библиотеке есть проверка согласованности, которая может предотвратить возникновение проблемы?
  • Я полагаю Array.Parallel.map сохранит порядок столбцов.

Вот код:

/// Build a matrix 
let buildMatrix selectedCols (frame: Frame<DateTime, String>) = 
    let matrix = 
        selectedCols 
        |> Array.map (fun colname -> frame.GetSeries(colname))
        |> Array.map (fun serie -> Series.values serie)
        |> Array.map (fun aSeq -> Seq.map unbox<float> aSeq)
        |> Array.map (fun aSeq -> Matrix(aSeq) )
        |> Array.reduce (fun acc matrix -> acc .| matrix)
    matrix.T

От кадра данных к временному ряду матриц строк

Я строю временные ряды матриц строк с помощью кода ниже.

  • Хранение данных в Серии должно гарантировать, что порядок строк сохраняется.
  • Как я могу отфильтровать столбцы и убедиться, что порядок столбцов точно такой же, как в массиве имен столбцов, передаваемых в функцию?

Вот код:

// Time series of row matrices - it'll be used to run a simulation
let timeSeriesOfMatrix frame = 
    frame
    |> Frame.filterRows (fun day target -> day >= startKalman)   
    |> Frame.mapRowValues ( fun row -> row.Values |> Seq.map unbox<float> )
    |> Series.mapValues( fun row -> Matrix(row) )

Большое спасибо.

PS: я сохранил все три сценария вместе, потому что я считаю, что три приведенных выше примера лучше помогут другим пользователям и мне понять, как работает библиотека, а не обсуждать каждый отдельный случай отдельно.

1 ответ

Решение

Чтобы ответить на первую часть, порядок меняется, потому что вы объединяете упорядоченные кадры (содержащие только одну серию), и конструкция кадра сохраняет порядок в этом случае. Вы, вероятно, можете заменить последние две строки, используя только Frame.ofColumns вместо использования явного соединения (это всегда будет делать внешнее соединение, но если вам нужно внутреннее соединение, вы можете использовать Frame.dropSparseRows отбросить пропущенные значения).

Во втором примере все выглядит хорошо - вы можете сэкономить некоторую работу, напрямую получая данные в виде числа с плавающей запятой;

frame.GetSeries<float>(colname).Values

Третий пример также выглядит хорошо, и вы можете сделать его немного короче:

row.As<float>().Values 
Другие вопросы по тегам