Apache spark spark中的自定义累加器类

Apache spark spark中的自定义累加器类,apache-spark,pyspark,Apache Spark,Pyspark,我想在pyspark中定义一个类型为List的累加器,并为工作节点累加字符串值。以下是我的代码: class ListParam(AccumulatorParam): def zero(self, v): return [] def addInPlace(self, acc1, acc2): acc1.extend(acc2) return acc1 然后我定义了一个这种类型的累加器,如下所示 accu = sc.accumulator([], ListParam(

我想在pyspark中定义一个类型为
List
的累加器,并为工作节点累加字符串值。以下是我的代码:

class ListParam(AccumulatorParam):
 def zero(self, v):
    return []
 def addInPlace(self, acc1, acc2):
    acc1.extend(acc2)
    return acc1
然后我定义了一个这种类型的累加器,如下所示

accu = sc.accumulator([], ListParam())
然后在executors中添加不同的值,如下所示

accu.add("abc")
class VectorAccumulatorParam(AccumulatorParam):
 def zero(self, value):
    return [0.0] * len(value)
 def addInPlace(self, val1, val2):
    for i in range(len(val1)):
        val1[i] += val2[i]
    return val1    
我希望值
abc
在累加器中仅显示为一个值,但累加器添加了三个不同的值(一个pr字符),当我查看驱动程序中的
accu
值时,它看起来像
['a','b','c']
。如何更改它,使其不会将每个字符作为单独的条目添加到累加器中

--------------编辑----------------

我为累加器定义了另一个自定义类,如下所示

accu.add("abc")
class VectorAccumulatorParam(AccumulatorParam):
 def zero(self, value):
    return [0.0] * len(value)
 def addInPlace(self, val1, val2):
    for i in range(len(val1)):
        val1[i] += val2[i]
    return val1    
在worker中,我有以下代码

global accu
accu += [accuracy]

但是当我在驱动程序中打印
accu
时,它是空的。有什么问题吗?

您是否试图明确告诉spark执行有关蓄能器的操作?您应该知道,很多时候您需要调用rdd.collect()来实际执行映射

您是否尝试显式地告诉spark执行处理累加器的操作?您应该知道,很多时候您需要调用rdd.collect()来实际执行映射

我遇到了与您相同的问题,看到了这个问题并处理了您的代码。下面的代码运行在带有(Py)Spark 2的HDP2.5集群上,对我有用

我接受了你的类并将其更改为附加字符串

from pyspark.accumulators import AccumulatorParam
class ListParam(AccumulatorParam):
    def zero(self, v):
        return []
    def addInPlace(self, variable, value):
        variable.append(value)
        return variable
然后我创建了一个累加器变量和一个测试数据帧:

accu = sc.accumulator([], ListParam()) 
rdd = sc.parallelize([(0,1), (0,1), (0,2), (1,2), (1,10), (1,20), (3,18), (3,18), (3,18)]) 
df=rdd.toDF(['id','score'])
对于我正在开发的程序,我必须将数据帧重新划分为单个大小。所以我也试过这个:

df.repartition(2)
之后,我创建了一个worker函数,它将向累加器列表追加一个字符串:

def worker(row):
    global accu
    accu.add("Moin")
现在我可以调用datafame的foreach循环(每个分区都是一个任务):

每个任务都会使用自己的字符串列表将一项附加到列表中:

>>> accu
Accumulator<id=66, value=[['Moin', 'Moin', 'Moin', 'Moin'], ['Moin', 'Moin', 'Moin', 'Moin', 'Moin']]>
结果:

>>> res
['Moin', 'Moin', 'Moin', 'Moin', 'Moin', 'Moin', 'Moin', 'Moin', 'Moin']

我和你有同样的问题,看到了这个问题,并使用了你的代码。下面的代码运行在带有(Py)Spark 2的HDP2.5集群上,对我有用

我接受了你的类并将其更改为附加字符串

from pyspark.accumulators import AccumulatorParam
class ListParam(AccumulatorParam):
    def zero(self, v):
        return []
    def addInPlace(self, variable, value):
        variable.append(value)
        return variable
然后我创建了一个累加器变量和一个测试数据帧:

accu = sc.accumulator([], ListParam()) 
rdd = sc.parallelize([(0,1), (0,1), (0,2), (1,2), (1,10), (1,20), (3,18), (3,18), (3,18)]) 
df=rdd.toDF(['id','score'])
对于我正在开发的程序,我必须将数据帧重新划分为单个大小。所以我也试过这个:

df.repartition(2)
之后,我创建了一个worker函数,它将向累加器列表追加一个字符串:

def worker(row):
    global accu
    accu.add("Moin")
现在我可以调用datafame的foreach循环(每个分区都是一个任务):

每个任务都会使用自己的字符串列表将一项附加到列表中:

>>> accu
Accumulator<id=66, value=[['Moin', 'Moin', 'Moin', 'Moin'], ['Moin', 'Moin', 'Moin', 'Moin', 'Moin']]>
结果:

>>> res
['Moin', 'Moin', 'Moin', 'Moin', 'Moin', 'Moin', 'Moin', 'Moin', 'Moin']