f# - 如何对 Deedle 中的非唯一列/索引进行左连接

标签 f# pandas deedle

我正在尝试在 Deedle 中的两个数据框之间进行左连接。两个数据框的示例如下:

let workOrders = 
    Frame.ofColumns [ 
        "workOrderCode" =?> series [ (20050,20050); (20051,20051); (20060,20060) ]
        "workOrderDescription" =?> series [ (20050,"Door Repair"); (20051,"Lift Replacement"); (20060,"Window Cleaning") ]]

// This does not compile due to the duplicate Work Order Codes
let workOrderScores = 
    Frame.ofColumns [ 
       "workOrderCode" => series [ (20050,20050); (20050,20050); (20051,20051) ]
       "runTime" => series [ (20050,20100112); (20050,20100130); (20051,20100215) ] 
       "score" => series [ (20050,100); (20050,120); (20051,80) ]] 

Frame.join JoinKind.Outer workOrders workOrderScores

问题是 Deedle 不允许我创建具有非唯一索引的数据框,并且出现以下错误:System.ArgumentException: Duplicate key '20050'。索引中不允许有重复的键。

有趣的是,在 Python/Pandas 中,我可以执行以下完美的操作。如何在 Deedle 中重现此结果?我在想我可能需要展平第二个数据框以删除重复项然后加入然后取消旋转/取消堆叠它?

workOrders = pd.DataFrame(
    {'workOrderCode': [20050, 20051, 20060],
        'workOrderDescription': ['Door Repair', 'Lift Replacement', 'Window Cleaning']})

workOrderScores = pd.DataFrame(
    {'workOrderCode': [20050, 20050, 20051],
        'runTime': [20100112, 20100130, 20100215],
        'score' : [100, 120, 80]})

pd.merge(workOrders, workOrderScores, on = 'workOrderCode', how = 'left')

# Result:
#   workOrderCode workOrderDescription   runTime  score
#0          20050          Door Repair  20100112    100
#1          20050          Door Repair  20100130    120
#2          20051     Lift Replacement  20100215     80
#3          20060      Window Cleaning       NaN    NaN

最佳答案

这是一个很好的问题 - 我不得不承认,目前没有使用 Deedle 的优雅方法来做到这一点。您能否向 GitHub 提交问题以确保我们跟踪此问题并添加一些解决方案?

正如您所说,Deedle 目前不允许您在键中使用重复值 - 尽管您的 Pandas 解决方案也不使用重复键 - 您只需使用 Pandas 允许您指定加入时要使用的列的事实(我认为这将是 Deedle 的重要补充)。

这是做你想做的一种方法 - 但不是很好。我认为使用透视将是另一种选择(最新的源代码中有一个很好的透视表函数 - NuGet 上还没有)。

我用过 groupByRowsnest将您的数据框转换为按 workOrderCode 分组的系列(现在每个项目都包含一个框架,其中所有行都具有相同的工作订单代码):

let workOrders = 
    Frame.ofColumns [ 
        "workOrderCode" =?> Series.ofValues [ 20050; 20051; 20060 ]
        "workOrderDescription" =?> Series.ofValues [ "Door Repair"; "Lift Replacement"; "Window Cleaning" ]]
   |> Frame.groupRowsByInt "workOrderCode"
   |> Frame.nest

let workOrderScores = 
    Frame.ofColumns [ 
       "workOrderCode" => Series.ofValues [ 20050; 20050; 20051 ]
       "runTime" => Series.ofValues [ 20100112; 20100130; 20100215 ] 
       "score" => Series.ofValues [ 100; 120; 80 ]] 
   |> Frame.groupRowsByInt "workOrderCode"
   |> Frame.nest

现在我们可以加入这两个系列(因为它们的工单代码是关键)。但是,然后您会为每个连接的订单代码获得一两个数据帧,并且需要大量工作来外部连接两个帧的行:
// Join the two series to align frames with the same work order code
Series.zip workOrders workOrderScores
|> Series.map(fun _ (orders, scores) -> 
    match orders, scores with
    | OptionalValue.Present s1, OptionalValue.Present s2 ->
        // There is a frame with some rows with the specified code in both 
        // work orders and work order scores - we return a cross product of their rows
        [ for r1 in s1.Rows.Values do
          for r2 in s2.Rows.Values do 
          // Drop workOrderCode from one series (they are the same in both)
          // and append the two rows & return that as the result
          yield Series.append r1 (Series.filter (fun k _ -> k <> "workOrderCode") r2) ]
        |> Frame.ofRowsOrdinal
    // If left or right value is missing, we just return the columns
    // that are available (others will be filled with NaN)
    | OptionalValue.Present s, _ 
    | _, OptionalValue.Present s -> s)
|> Frame.unnest
|> Frame.indexRowsOrdinally

这可能很慢(尤其是在 NuGet 版本中)。如果您处理更多数据,请尝试从源代码构建最新版本的 Deedle(如果这没有帮助,请提交问题 - 我们应该调查一下!)

关于f# - 如何对 Deedle 中的非唯一列/索引进行左连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21814027/

相关文章:

sql - F#:如何使用 SQL 数据源创建 Deedle Frame

types - F# 奇怪的类型错误消息

f# - 在 F# 中将序列包装在流中

python - 如何有效地将 python pandas 数据框保存在 hdf5 中并在 R 中将其作为数据框打开?

python - html 中的 Pandas 数据分析

csv - 更改 Deedle Frame 中的数据类型

f# - 格式化内置类型以在 Deedle 中进行 pretty-print

f# - fparsec 解析字符串序列

c# - 有人在任何完整项目中使用过 WebSharper 吗?

python - 合并两个 Pandas 数据帧,在一个时间列上重新采样,插值