首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >交叉连接与Deedle

交叉连接与Deedle
EN

Stack Overflow用户
提问于 2021-08-30 21:14:15
回答 1查看 90关注 0票数 2

我正试图通过分析我的电费来学习一些F#和Deedle。

假设我有两个框架,一个包含我的电量:

代码语言:javascript
复制
let consumptionsByYear = 
  [ (2019, "Total", 500); (2019, "Day", 200); (2019, "Night", 300);
    (2020, "Total", 600); (2020, "Day", 250); (2020, "Night", 350) ]
  |> Frame.ofValues
代码语言:javascript
复制
        Total Day Night 
2019 -> 500   200 300   
2020 -> 600   250 350   

另一项计划有两项定价结构不同的计划(一项固定费用或根据一天中的时间而变化的费用):

代码语言:javascript
复制
let prices = 
  [ ("Plan A", "Base fee", 50); ("Plan A", "Fixed price", 3); ("Plan A", "Day price", 0); ("Plan A", "Night price", 0);
    ("Plan B", "Base fee", 40); ("Plan B", "Fixed price", 0); ("Plan B", "Day price", 5); ("Plan B", "Night price", 2) ]
  |> Frame.ofValues
代码语言:javascript
复制
          Base fee Fixed price Day price Night price 
Plan A -> 50       3           0         0           
Plan B -> 40       0           5         2           

以前,我在SQL中使用交叉联接解决了这个问题,在Excel中使用了嵌套联接。为了复制这些输出,我找到了Frame.mapRows,但是使用它构建预期的输出似乎非常繁琐:

代码语言:javascript
复制
let costs = consumptionsByYear
            |> Frame.mapRows (fun _year cols ->
                ["Total price" => (prices?``Base fee``
                    + (prices?``Fixed price`` |> Series.mapValues ((*) (cols.GetAs<float>("Total"))))
                    + (prices?``Day price`` |> Series.mapValues ((*) (cols.GetAs<float>("Day"))))
                    + (prices?``Night price`` |> Series.mapValues ((*) (cols.GetAs<float>("Night"))))
                    )]
                |> Frame.ofColumns)
            |> Frame.unnest
代码语言:javascript
复制
               Total price 
2019 Plan A -> 1550        
     Plan B -> 1640        
2020 Plan A -> 1850        
     Plan B -> 1990        

有没有更好的方法,甚至是小小的改进?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-31 04:33:59

我不是Deedle专家,但我认为这基本上是:

  • 两个矩阵的点乘积:consumptionsByYear和周期昼夜价格,
  • 然后加上不变价格。

换言之:

代码语言:javascript
复制
 consumptionsByYear      periodicPrices               basePrices
 -------------------     ------------------------     ---------------------------
|         Day Night |   |          Plan A Plan B |   |             Plan A Plan B |
| 2019 -> 200 300   | * | Day   -> 3      5      | + | Base fee -> 50     40     |
| 2020 -> 250 350   |   | Night -> 3      2      |    ---------------------------
 -------------------     ------------------------

考虑到这种方法,我会这样做:

代码语言:javascript
复制
open Deedle
open Deedle.Math

let consumptionsByYear = 
    [ (2019, "Day", 200); (2019, "Night", 300)
      (2020, "Day", 250); (2020, "Night", 350) ]
    |> Frame.ofValues

let basePrices =
    [ ("Plan A", "Base fee", 50)
      ("Plan B", "Base fee", 40) ]
    |> Frame.ofValues
    |> Frame.transpose

let periodicPrices =
    [ ("Plan A", "Day", 3); ("Plan A", "Night", 3)
      ("Plan B", "Day", 5); ("Plan B", "Night", 2) ]
    |> Frame.ofValues
    |> Frame.transpose

// repeat the base prices for each year
let basePricesExpanded =
    let row = basePrices.Rows.["Base fee"]
    consumptionsByYear
        |> Frame.mapRowValues (fun _ -> row)
        |> Frame.ofRows

let result =
    Matrix.dot(consumptionsByYear, periodicPrices) + basePricesExpanded
result.Print()

产出如下:

代码语言:javascript
复制
        Plan A Plan B
2019 -> 1550   1640
2020 -> 1850   1990

为了简单起见,我做了一些修改:

  • consumptionsByYear
    • 为了使矩阵兼容,我将从整数到字符串的年份进行了映射。
    • 我删除了Total列,因为它可以从其他两个派生出来。

  • prices
    • 我把它分解成两个不同的框架:一个是周期价格,另一个是基价,然后转换它们来实现矩阵乘法。
    • 我将Day price改为Day,将Night price更改为Night,以使矩阵兼容。
    • 我去掉了Fixed price列,因为它可以在DayNight列中表示。

更新:从Deedle 2.4.2开始,不再需要将年份映射到字符串。我已经相应地修改了我的解决方案。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68990397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档