Карта для рамки Deedle
Я учу F#. Я пытаюсь преобразовать Map<string, seq<DateTime * float>>
к кадру данных Deedle ( http://bluemountaincapital.github.io/Deedle/tutorial.html).
Я подготовил следующий код:
let folderFnct (aFrame:Frame) colName datesAndValues =
let newSerie = Series(Seq.map (fun x -> fst x) datesAndValues, Seq.map (fun y -> snd y) datesAndValues)
let newFrame = aFrame.Join([colName], [newSerie], kind=JoinKind.Inner)
newFrame
let mapToDeedleFrame myMap frame =
Map.fold ( fun s ticker datesAndValues -> folderFnct s ticker datesAndValues) frame myMap
mapToDeedleFrame
сворачивает карту, используя существующий кадр. Функция папки folderFnct
:
- берет кадр
- использует ключ карты в качестве имени столбца во фрейме, и
- обрабатывает значения (
<DateTime * float>
Делая серию из них.
Проблема с:
let newFrame = aFrame.Join([colName], [newSerie], kind=JoinKind.Inner)
где:
Поле, конструктор или член 'Join' не определены
Я определил три потенциальных причины проблемы:
- Почему
aFrame.Join
не определен? Я пытался явно указать типaFrame
- Как я могу кормить
mapToDeedleFrame
пустая рамка? - Должен ли я образец совпадения в
folderFnct
против случая, когдаaFrame
пустой?
Большое спасибо!
РЕДАКТИРОВАТЬ 1
Исходя из предположения Томаса, это то, что я до сих пор проверял.
let folderFnct (aFrame:Frame<'a, 'b>) columnName (seqOfTuples: seq<'a*'b>) =
let newSerie = Series(Seq.map (fun x -> fst x) seqOfTuples, Seq.map (fun y -> snd y) seqOfTuples)
let otherFrame = Frame([columnName], [newSerie])
let newFrame = aFrame.Join((otherFrame), kind=JoinKind.Inner)
newFrame
let mapToDeedleFrame myMap frame =
Map.fold ( fun state k vals -> folderFnct state k vals) frame myMap
Последний пропущенный шаг: как быстро передать пустой фрейм (возможно, избегая создания фиктивного) в mapToDeedleFrame
? я пытался []
как в
let frame = mapToDeedleFrame mapTS []
Это может быть глупый вопрос, но я новичок в F#, и мне было интересно, если есть Empty
Тип построен на языке.
СЛЕДУЙТЕ ЗА ВОПРОСОМ
В исходном файле, который я прочитал ( https://github.com/BlueMountainCapital/Deedle/blob/master/src/Deedle/Frame.fs):
member frame.Join<'V>(colKey, series:Series<'TRowKey, 'V>, kind, lookup) =
let otherFrame = Frame([colKey], [series])
frame.Join(otherFrame, kind, lookup)
пока в описании функции выскочил на экран:
Из рисунка выше я бы предположил, что тип Frame такой же, как и у colKey, в то время как, как я понял, colKey - это просто ключ к столбцу dataframe, добавляемому с объединением из серии. Как полный нуб, я совсем запутался..
РЕДАКТИРОВАТЬ 2
Я переписал код:
let seriesListMapper (colName:string, series:Series<'a, 'b>) =
[colName => series] |> frame
let frameListReducer (accFrame: Frame<'a, 'b>) (aFrame: Frame<'a, 'b>) =
accFrame.Join(aFrame, kind=JoinKind.Outer)
let seriesListToFrame (seriesList: List<string * Series<'a, 'b>>) =
seriesList |> List.map (fun elem -> seriesListMapper elem) |> List.reduce(fun acc elem -> frameListReducer acc elem)
Проблема в том, что:
let frame = seriesListToFrame seriesList
возвращает frame как Frame, а вместо этого seriesList (string *Series<DateTime, float>) list
Я думаю, что проблема с:
let seriesListMapper (colName:string, series:Series<'a, 'b>) =
[colName => series] |> frame
по факту seriesListMapper
обозначается как
seriesListMapper: colName:string * series:Series<'a, 'b> -> Frame<'a, string>
Я не понимаю, как и почему значения преобразуются в string
от float
,
Одна интересная вещь заключается в том, что построение кадра с frame.Format()
фактически подтверждает, что данные выглядят правильно. Именно это "странное" преобразование в string
,
1 ответ
В аннотации типа folderFnct
, у тебя есть aFrame:Frame
, Однако тип, представляющий фреймы данных, является универсальным типом с двумя аргументами типа (представляющими тип индекса для строк и столбцов соответственно), поэтому аннотация должна быть aFrame:Frame<_, _>
,
Еще один способ добавить ряды во фрейм - использовать операцию мутации:
aFrame.AddSeries(colName, newSeries)
Тем не менее, это поддерживает только левое соединение (фрейм данных может быть видоизменен только путем добавления новых серий, но не таким образом, чтобы это могло изменить индекс). Однако вы можете использовать этот подход, а затем удалить все пропущенные значения из фрейма после его построения.
РЕДАКТИРОВАТЬ: Чтобы ответить на вопрос о родовых типах:
Series<K, V>
представляет серию с ключами типаK
содержащие значения типаV
(например, ряды с обычно индексируемыми наблюдениямиK=int
а такжеV=float
)Frame<R, C>
представляет фрейм, который содержит разнородные данные (потенциально разных типов для каждого столбца), где строки индексируютсяR
и столбцы индексируютсяC
, Для обычно индексируемого кадраR=int
и, как правило, ваши столбцы будут названы такC=string
(но вы можете иметь и другие показатели)