Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何计算;“自定义运行总数”;在spark 1.5数据帧中_Python_Scala_Apache Spark_Dataframe_Apache Spark Sql - Fatal编程技术网

Python 如何计算;“自定义运行总数”;在spark 1.5数据帧中

Python 如何计算;“自定义运行总数”;在spark 1.5数据帧中,python,scala,apache-spark,dataframe,apache-spark-sql,Python,Scala,Apache Spark,Dataframe,Apache Spark Sql,我有一个存储在拼花地板文件中的每个贷款的贷款支付历史记录,并尝试计算每个贷款期间的“过期”金额。 如果不是计算到期金额的复杂性质,这将是一个简单的窗口分区任务 如果客户支付的金额少于到期金额,则增加逾期金额,另一方面,如果客户支付预付款,则在后续期间忽略额外付款(以下示例中的第5行和第6行) 似乎有效 在这次旅程中,我在pyspark实现中发现了几个bug 类行中调用的实现错误 该行的构造函数中存在令人讨厌的错误。没有明显的原因,新的排序 列,所以在旅程结束时,我的结果表有列 按字母顺序排列。这

我有一个存储在拼花地板文件中的每个贷款的贷款支付历史记录,并尝试计算每个贷款期间的“过期”金额。 如果不是计算到期金额的复杂性质,这将是一个简单的窗口分区任务

如果客户支付的金额少于到期金额,则增加逾期金额,另一方面,如果客户支付预付款,则在后续期间忽略额外付款(以下示例中的第5行和第6行)

似乎有效

在这次旅程中,我在pyspark实现中发现了几个bug

  • 类行中调用的实现错误
  • 该行的构造函数中存在令人讨厌的错误。没有明显的原因,新的排序 列,所以在旅程结束时,我的结果表有列 按字母顺序排列。这只会让我们更难看到 最终结果

  • 既不漂亮也不高效,但应该给你一些工作的机会。让我们从创建和注册表开始:

    val df = sc.parallelize(Seq(
      (1, 1, 100, 100), (1, 2, 100, 60), (1, 3, 100, 100),
      (1, 4, 100, 200), (1, 5, 100, 110), (1, 6, 100, 80),
      (1, 7, 100, 60), (1, 8, 100, 100), (2, 1, 150, 150),
      (2, 2, 150, 150), (2, 3, 150, 150), (3, 1, 200, 200),
      (3, 2, 200, 120), (3, 3, 200, 120)
    )).toDF("LoanID", "Period", "DueAmt", "ActualPmt")
    
    df.registerTempTable("df")
    
    接下来,让我们定义并注册一个UDF:

    case class Record(period: Int, dueAmt: Int, actualPmt: Int, pastDue: Int)
    
    def runningPastDue(idxs: Seq[Int], dues: Seq[Int], pmts: Seq[Int]) = {
      def f(acc: List[(Int, Int, Int, Int)], x: (Int, (Int, Int))) = 
        (acc.head, x) match {
          case ((_, _, _, pastDue), (idx, (due, pmt))) => 
            (idx, due, pmt, (pmt - due + pastDue).min(0)) :: acc
        }
    
      idxs.zip(dues.zip(pmts))
        .toList
        .sortBy(_._1)
        .foldLeft(List((0, 0, 0, 0)))(f)
        .reverse
        .tail
        .map{ case (i, due, pmt, past) => Record(i, due, pmt, past) }
    }
    
    sqlContext.udf.register("runningPastDue", runningPastDue _)
    
    汇总,并计算总和:

    val aggregated = sqlContext.sql("""
      SELECT LoanID, explode(pmts) pmts FROM (
        SELECT LoanId, 
               runningPastDue(
                 collect_list(Period), 
                 collect_list(DueAmt), 
                 collect_list(ActualPmt)
               ) pmts
        FROM df GROUP BY LoanID) tmp""")
    
    val flattenExprs = List("Period", "DueAmt", "ActualPmt", "PastDue")
      .zipWithIndex
      .map{case (c, i) => col(s"tmp._${i+1}").alias(c)}
    
    最后展平:

    val result = aggregated.select($"LoanID" :: flattenExprs: _*)
    

    既不漂亮也不高效,但应该给你一些工作的机会。让我们从创建和注册表开始:

    val df = sc.parallelize(Seq(
      (1, 1, 100, 100), (1, 2, 100, 60), (1, 3, 100, 100),
      (1, 4, 100, 200), (1, 5, 100, 110), (1, 6, 100, 80),
      (1, 7, 100, 60), (1, 8, 100, 100), (2, 1, 150, 150),
      (2, 2, 150, 150), (2, 3, 150, 150), (3, 1, 200, 200),
      (3, 2, 200, 120), (3, 3, 200, 120)
    )).toDF("LoanID", "Period", "DueAmt", "ActualPmt")
    
    df.registerTempTable("df")
    
    接下来,让我们定义并注册一个UDF:

    case class Record(period: Int, dueAmt: Int, actualPmt: Int, pastDue: Int)
    
    def runningPastDue(idxs: Seq[Int], dues: Seq[Int], pmts: Seq[Int]) = {
      def f(acc: List[(Int, Int, Int, Int)], x: (Int, (Int, Int))) = 
        (acc.head, x) match {
          case ((_, _, _, pastDue), (idx, (due, pmt))) => 
            (idx, due, pmt, (pmt - due + pastDue).min(0)) :: acc
        }
    
      idxs.zip(dues.zip(pmts))
        .toList
        .sortBy(_._1)
        .foldLeft(List((0, 0, 0, 0)))(f)
        .reverse
        .tail
        .map{ case (i, due, pmt, past) => Record(i, due, pmt, past) }
    }
    
    sqlContext.udf.register("runningPastDue", runningPastDue _)
    
    汇总,并计算总和:

    val aggregated = sqlContext.sql("""
      SELECT LoanID, explode(pmts) pmts FROM (
        SELECT LoanId, 
               runningPastDue(
                 collect_list(Period), 
                 collect_list(DueAmt), 
                 collect_list(ActualPmt)
               ) pmts
        FROM df GROUP BY LoanID) tmp""")
    
    val flattenExprs = List("Period", "DueAmt", "ActualPmt", "PastDue")
      .zipWithIndex
      .map{case (c, i) => col(s"tmp._${i+1}").alias(c)}
    
    最后展平:

    val result = aggregated.select($"LoanID" :: flattenExprs: _*)
    

    谢谢你的样品。我一直在寻找这样的解决方案。我将比较您的解决方案在实际数据上的性能与使用DF->RDD->DF的解决方案的性能。我会给你留言的不客气。但我并不是特别热情<代码>收集列表这里感觉不对。感谢您提供的示例。我一直在寻找这样的解决方案。我将比较您的解决方案在实际数据上的性能与使用DF->RDD->DF的解决方案的性能。我会给你留言的不客气。但我并不是特别热情<代码>收集列表这里感觉不对。