Нахождение Stats.max для каждого иерархического индекса в Deedle - PullRequest
2 голосов
/ 14 февраля 2020

Если у меня есть набор данных, который содержит [Город, Дилерство, Общее количество проданных автомобилей]. Как бы мне получить лучшего дилера в каждом городе и количество проданных автомобилей?

Результаты должны выглядеть следующим образом:

City1 Dealership A 2000
City2 Dealership X 1000
etc.

Я уверен, что это возможно, но я не мне повезло, и это может произойти, потому что я подхожу к проблеме неправильно.

В настоящее время я группируюсь по дилерским центрам и городам, которые создают Frame<(string*string*int), int> и получают меня

City1 Dealership A 1 -> 2000
City1 Dealership B 2 -> 1000
City2 Dealership X 3 -> 1000
City2 Dealership Y 4 -> 500
etc.

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

Спасибо.

Ответы [ 2 ]

1 голос
/ 19 февраля 2020

Я адаптировал ответ Томаса и вывел тип как Series<string, (string * int)>

let data = series [
  ("City1", "Dealership A") => 2000
  ("City1", "Dealership B") => 1000
  ("City2", "Dealership X") => 1000
  ("City2", "Dealership Y") => 500 ]

data
|> Series.groupBy (fun k _ -> fst k)
|> Series.mapValues (fun sr ->
  let sorted = sr |> Series.sortBy(fun x -> -x)
  let key = sorted |> Series.firstKey |> snd
  let value = sorted |> Series.firstValue
  key, value )

Вывод выглядит как

City1 -> (Dealership A, 2000) 
City2 -> (Dealership X, 1000) 

EDITED

Я предполагаю, что у вас есть CSV-файл, подобный этому

City,Dealership,TotalCarsSold
City1,Dealership A,2000
City1,Dealership B,1000
City2,Dealership X,1000
City2,Dealership Y,500

Вот как я это сделаю. Прочитайте его как Frame, получите столбец как Series и примените тот же код выше, чтобы получить результат.

let df = 
  Frame.ReadCsv("C:/Temp/dealership.csv")
  |> Frame.indexRowsUsing(fun r -> r.GetAs<string>("City"), r.GetAs<string>("Dealership"))
df?TotalCarsSold
|> Series.groupBy (fun k _ -> fst k)
|> Series.mapValues (fun sr ->
  let sorted = sr |> Series.sortBy(fun x -> -x)
  let key = sorted |> Series.firstKey |> snd
  let value = sorted |> Series.firstValue
  key, value )
1 голос
/ 14 февраля 2020

Вы можете сделать это, используя функцию Series.applyLevel. Он принимает серию вместе с селектором ключа, а затем применяет данную агрегацию ко всем строкам, имеющим данный ключ. В вашем случае ключевой селектор просто должен спроектировать дилерский центр из составленного ключа серии. Учитывая ваши данные образца:

let data = series [
  ("City1", "Dealership A") => 2000
  ("City1", "Dealership B") => 1000
  ("City2", "Dealership X") => 1000
  ("City2", "Dealership Y") => 500 ]

Вы можете получить результат, используя:

data 
|> Series.applyLevel (fun (c, d) -> d) Stats.max

Обратите внимание, что Stats.max возвращает option (что составляет None для пустой серии) , Вы можете получить серию только с цифрами, используя:

data 
|> Series.applyLevel (fun (c, d) -> d) (Stats.max >> Option.get)
...