Как перебрать серию 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
на каждом чанке также должно быть достаточно быстро, потому что Дидл знает, что все элементы в чанке имеют одинаковый индекс. (В качестве альтернативы, вы можете перебирать отдельные строки, но это сделает его длиннее).