一种更有效的计算火花数据帧的方法

时间:2016-10-14 16:48:00

标签: python apache-spark pyspark

我的销售数据框类似于:

id   | date              | amount  
-----|-------------------|-------
1    |2016-03-04 12:03:00|10.40
1    |2016-03-04 12:05:10|5.0
1    |2016-03-04 12:15:50|11.30
1    |2016-03-04 12:16:00|9.40
1    |2016-03-04 12:30:00|10.0
1    |2016-03-04 12:40:00|5.40

我正在尝试按时间分组10分钟并将金额相加并创建一个类似于的数据框:

date             | amount  
-----------------|-------
2016-03-04 12:00 |0.0
2016-03-04 12:10 |15.40
2016-03-04 12:20 |20.70
2016-03-04 12:30 |10.0
2016-03-04 12:40 |5.40

我试图循环一个日期时间变量,过滤数据帧,组和总和而不是附加到列表并使用列表创建数据帧。

bar_list = []
while date_loop < final_date:
    start_time = date_loop - datetime.timedelta(minutes=10)
    end_time = date_loop - datetime.timedelta(seconds=1)
    df_range = (df_sale
               .filter((df_sale.date >= start_time) & (df_sale.date <= end_time))
               .groupby()
               .sum('amount'))
  bar_list.append((date_loop,df_range.head()['sum(amount)']))
  date_loop += datetime.timedelta(minutes=10)

fields = ['date','amount']
df = sqlContext.createDataFrame(bar_list,fields).na.fill(0)

在包含214626行的文件中,此代码最多可能需要20分钟才能计算出10分钟时间范围内2个月的销售额。

有没有更有效的方法呢?我明白我可以在工人之间共享变量,可以共享一个列表吗?是否在我的瓶颈上贴上了这个名单?

谢谢。

1 个答案:

答案 0 :(得分:0)

如果你想以字符串形式处理,这可能有点脏,你可以试试这个:

def getDTClosestMin(s:String):String = {
 s.substring(0,4)+"-"+s.substring(5,7)+"-"+s.substring(8,10)+" " +
 s.substring(11,13)+":" +
 ((((s.substring(14,16)).toInt)*0.1).ceil)*10).round.toString.padTo(2,"0").mkString }


timeAmtRDD.map(x=> x._1+","+x._2+","+x._3)
  .map(x=>x.split(","))
  .map(x=> (getDTClosestMin(x(1)), x(2).toFloat))
  .reduceByKey(_+_)
  .sortByKey().toDF("date", "amount").show()


Output:
+----------------+------+
|            date|amount|
+----------------+------+
|2016-03-04 12:10|  15.4|
|2016-03-04 12:20|  20.7|
|2016-03-04 12:30|  10.0|
|2016-03-04 12:40|   5.4|
+----------------+------+

更新这段时间..;)