Как перебрать серию Deedle<DateTime, Series <DateTime, ObjectSeries <string >>

Я создал фрейм данных, используя

// Create a dataframe containing the Open, High, Low, and Close
let ohlc =
cl 
|> Frame.sliceCols ["Open"; "High"; "Low"; "Close"; "Volume"]

с полученным результатом: Open High Low Close Volume 12/28/2014 20:00:00 PM -> 62,13 62,67 62,13 62,27 3206
28.12.2014 21:00:00 -> 62.27 62.42 62.14 62.39 1620
28.12.2014 22:00:00 -> 62,4 62,41 62,16 62,21 1275
28.12.2014 23:00:00 -> 62,21 62,32 61,96 62,19 2791
29.12.2014, 12:00:00 -> 62.17 62.25 62.08 62.23 1233
29.12.2014 1:00:00 -> 62.23 62.41 62.21 62.31 1186
29.12.2014 2:00:00 -> 62.32 62.32 62.07 62.21 1446
29.12.2014 3:00:00 -> 62,22 62,35 62,17 62,28 1335

Теперь я хочу сгенерировать более высокие временные рамки (ежедневно) из вышеупомянутой почасовой выборки.

Я начинаю с:

ohlc
|> Frame.rows
|> Series.resampleEquiv (fun d -> d.Date)

который возвращает: Series<DateTime,Series<DateTime,ObjectSeries<string>>>.

Я хочу создать новый DataFrame, содержащий столбцы Date(key), Open, High, Low, Close и Volume. Раскрытие является первым открытием в ряду 1 серии. Максимум Максимум Максимум в серии. Минимум минимальный минимум в серии. Закрыть это последний Закрыть в серии. Объем - это сумма объема в серии

Так что-то вроде:

ohlc
|> Frame.rows
|> Series.resampleEquiv (fun d -> d.Date)
|> ??
|> ??

Вместо того, чтобы пытаться сделать это на уровне фреймов, используя строки, лучше ли мне делать это с фреймами, используя столбцы?

ОБНОВЛЕНИЕ Вот готовый код:

ohlc
|> Frame.rows
|> Series.resampleEquiv (fun d -> d.Date)
|> Series.mapValues (fun s ->
   let temp = Frame.ofRows s 
   series ["Open"  => Series.firstValue temp?Open
           "High"  => defaultArg (Stats.max temp?High) nan
           "Low"   => defaultArg (Stats.min temp?Low) nan
           "Close" => Series.lastValue temp?Close 
           "Volume" => defaultArg (Some( Stats.sum temp?Volume) ) nan ] )
|> Frame.ofRows

Я не смог использовать:

"Volume" => defaultArg (Stats.sum temp?Volume) nan ] )

так как это дало мне сообщение об ошибке: ожидалось, что это выражение будет иметь тип float, но здесь имеет тип float. Мне пришлось обернуть функцию Some(). Не уверен, почему Stats.sum требует этого, а Stat.max и Stats.min - нет.

1 ответ

Решение

После звонка resampleEquivв итоге получается серия (представляющая фрагменты с одинаковой датой) серии (представляющая значения с разным временем, но с одной и той же датой) серии объектов (представляющая разные столбцы исходного кадра).

Вы можете перебирать ряды верхнего уровня и превращать каждый из рядов серии объектов (каждый кусок) обратно в кадр. Затем вы можете выполнить агрегирование по фрейму и вернуть новую строку:

source
|> Series.resampleEquiv (fun d -> d.Date.Year)
|> Series.mapValues (fun s -> 
    let temp = Frame.ofRows s
    series [ "Open" => Series.firstValue temp?Open
             "High" => defaultArg (Stats.max temp?High) nan ])
|> Frame.ofRows

Я сделал это только для Open и High, но вы можете увидеть идею:-). Вызов Frame.ofRows на каждом чанке также должно быть достаточно быстро, потому что Дидл знает, что все элементы в чанке имеют одинаковый индекс. (В качестве альтернативы, вы можете перебирать отдельные строки, но это сделает его длиннее).

Другие вопросы по тегам