如何根据价值在spark中映射多对多?

时间:2018-01-19 10:38:37

标签: apache-spark pyspark

对于输入数据帧:

+-------+-----+-------+------+--------------+-------+----+
|Closing| Flow|Opening|Period|        RowKey|RowKey2|Year|
+-------+-----+-------+------+--------------+-------+----+
|  -2.11|-2.11|    0.0|    01|2016-01-1200-A| 1200-A|2016|
|  -1.11|-1.11|    0.0|    01|2016-01-1200-B| 1200-B|2016|
|   -1.0| -1.0|    0.0|    04|  2016-04-2200|   2200|2016|
|   -1.0| -1.0|    0.0|    04|  2016-04-3000|   3000|2016|
|   -1.0| -1.0|    0.0|    05|2016-05-1200-C| 1200-C|2016|
|    0.0|  1.0|   -1.0|    05|  2016-05-3000|   3000|2016|
|    0.0|  1.0|   -1.0|    08|  2016-08-2200|   2200|2016|
|    1.0|  1.0|    0.0|    09|  2016-09-2200|   2200|2016|
|   -2.0| -1.0|   -1.0|    12|2016-12-1200-C| 1200-C|2016|
|  100.0|100.0|    0.0|    12|  2016-12-4000|   4000|2016|
+-------+-----+-------+------+--------------+-------+----+

我想从下面应用函数(其中period是输入[" Period]列中不同期间值的列表):

def insertPeriod(row, period):
    row = row.asDict()
    row["Period"]=period
    return Row(**row)

def filterOutFromPartion(aggdata, periods):
    output = []
    for period in periods:
        iterator = (item for item in aggdata if item["Period"] == period)
        try:
            found = next(iterator)
            output.append(insertPeriod(found,period))
        except StopIteration:
            if (len(output)==0):
                continue
            else:
                temp = output[-1]
                output.append(insertPeriod(temp,period))
    return iter(output)

结果将是:

+--------------+----+------+-------------+-----+--------------+--------------+
|        RowKey|Year|Period|AccountNumber| Flow|OpeningBalance|ClosingBalance|
+--------------+----+------+-------------+-----+--------------+--------------+
|2016-01-1200-A|2016|     1|         1200|-2.11|             0|         -2.11|
|2016-01-1200-B|2016|     1|         1200|-1.11|             0|         -1.11|
|2016-02-1200-A|2016|     2|         1200|    0|         -2.11|         -2.11|
|2016-02-1200-B|2016|     2|         1200|    0|         -1.11|         -1.11|
|2016-03-1200-A|2016|     3|         1200|    0|         -2.11|         -2.11|
|2016-03-1200-B|2016|     3|         1200|    0|         -1.11|         -1.11|
|2016-04-1200-A|2016|     4|         1200|    0|         -2.11|         -2.11|
|2016-04-1200-B|2016|     4|         1200|    0|         -1.11|         -1.11|
| 2016-04-2200-|2016|     4|         2200|   -1|             0|            -1|
| 2016-04-3000-|2016|     4|         3000|   -1|             0|            -1|
|2016-05-1200-A|2016|     5|         1200|    0|         -2.11|         -2.11|
|2016-05-1200-B|2016|     5|         1200|    0|         -1.11|         -1.11|
|2016-05-1200-C|2016|     5|         1200|   -1|             0|            -1|
| 2016-05-2200-|2016|     5|         2200|    0|            -1|            -1|
| 2016-05-3000-|2016|     5|         3000|    1|            -1|             0|
|2016-06-1200-A|2016|     6|         1200|    0|         -2.11|         -2.11|
|2016-06-1200-B|2016|     6|         1200|    0|         -1.11|         -1.11|
|2016-06-1200-C|2016|     6|         1200|    0|            -1|            -1|
| 2016-06-2200-|2016|     6|         2200|    0|            -1|            -1|
| 2016-06-3000-|2016|     6|         3000|    0|             0|             0|
+--------------+----+------+-------------+-----+--------------+--------------+
only showing top 20 rows

基本上将一个map操作放在rdd上,按RowKey2值分组,如果有关于句点的信息缺失,那么只需使用上一个信息(如果存在)。

所以我很乐意使用

 df.rdd.partitionBy("RowKey2")\
.mapPartitions(lambda x: filterOutFromPartion(x, periodsList))\
.collect()

哪个上升

  

Py4JError:调用时发生错误   None.org.apache.spark.api.python.PythonPartitioner。跟踪:   py4j.Py4JException:构造函数   org.apache.spark.api.python.PythonPartitioner([class java.lang.String,   class java.lang.Long])不存在

如果我按键跳过分区,那么我只得到2个第一个Rowkeys的结果(每个12个句点如预期的那样)。有人可以在那里给我一些帮助吗?

此致 麦克

1 个答案:

答案 0 :(得分:0)

partitionBy签名:

  

partitionBy(numPartitions,partitionFunc =)

其中第一个参数是整数,第二个参数是一个函数。没有接受字符串的变体。您可能会将其与Dataframe.repartition

混淆
df.repartition(n, "RowKey2")

partitionBy

df.rdd.keyBy(lambda x: x.RowKey2).partitionBy(n)

看起来你假设partitionBy的工作方式与groupByKey类似,并且你得到一个RowKey的项目。事实并非如此:How does HashPartitioner work?