如何使用PySpark进行嵌套for-each循环

时间:2016-08-25 22:54:29

标签: python apache-spark pyspark

想象一个大型数据集(> 40GB镶木地板文件),其中包含数千个变量的值观察值,即三元组(变量,时间戳,值)

现在想一下您只对500个变量的子集感兴趣的查询。并且您想要检索特定时间点(观察窗口或时间范围)的那些变量的观察值(值 - >时间序列)。这样有一个开始和结束时间。

如果没有分布式计算(Spark),您可以像这样编写代码:

for var_ in variables_of_interest:
    for incident in incidents:

        var_df = df_all.filter(
            (df.Variable == var_)
            & (df.Time > incident.startTime)
            & (df.Time < incident.endTime))

我的问题是:如何使用Spark / PySpark做到这一点?我在考虑:

  1. 以某种方式将事件与变量联系起来,然后过滤数据帧。
  2. 广播事件数据帧并在过滤变量观察值(df_all)时在map-function中使用它。
  3. 以某种方式使用RDD.cartasian或RDD.mapParitions(注释:镶木地板文件由变量分割保存)。
  4. 预期输出应为:

    incident1 --> dataframe 1
    incident2 --> dataframe 2
    ...
    

    数据框1包含所有变量及其在事件1和数据帧2的时间范围内的观察值,这些值在事件2的时间范围内。

    我希望你明白了。

    更新

    我尝试编写基于思路#1的解决方案和来自zero323给出的答案的代码。工作得很好,但我想知道如何在最后一步中将其汇总/分组到事件中?我尝试为每个事件添加一个序号,但后来我在最后一步遇到了错误。如果您可以查看和/或完成代码,那将会很酷。因此我上传了示例数据和脚本。环境是Spark 1.4(PySpark):

1 个答案:

答案 0 :(得分:1)

一般来说,只有第一种方法对我来说才合理。关于记录和分布数量的完全加入策略,但您可以创建顶级数据框:

ref = sc.parallelize([(var_, incident) 
    for var_ in variables_of_interest:
    for incident in incidents
]).toDF(["var_", "incident"])

并简单地join

same_var = col("Variable") == col("var_")
same_time = col("Time").between(
    col("incident.startTime"),
    col("incident.endTime")
)

ref.join(df.alias("df"), same_var &  same_time)

或对特定分区执行联接:

incidents_ = sc.parallelize([
   (incident, ) for incident in incidents
]).toDF(["incident"])

for var_ in variables_of_interest:
    df = spark.read.parquet("/some/path/Variable={0}".format(var_))
    df.join(incidents_, same_time)

可选marking one side as small enough to be broadcasted