Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/306.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 数据流:在前一个beam.combiner的结果上使用beam.combiner_Python_Google Cloud Dataflow_Apache Beam - Fatal编程技术网

Python 数据流:在前一个beam.combiner的结果上使用beam.combiner

Python 数据流:在前一个beam.combiner的结果上使用beam.combiner,python,google-cloud-dataflow,apache-beam,Python,Google Cloud Dataflow,Apache Beam,我正在使用Beam管道来计算流数据的电话号码频率。我使用滑动窗口,每5分钟重复一次,总时间为15分钟,所以正如预期的那样,对于一些输入,当输入落在多个窗口中时,我会得到多个输出 在计算出现次数之后,我想找到输入特征的平均值。输入是元组,如: ('phone_number', '123') ('phone_number', '456') ('phone_number', '456') ('phone_number', '456') 管道的第一部分是计算每个数字的频率: | 'window' &g

我正在使用Beam管道来计算流数据的电话号码频率。我使用滑动窗口,每5分钟重复一次,总时间为15分钟,所以正如预期的那样,对于一些输入,当输入落在多个窗口中时,我会得到多个输出

在计算出现次数之后,我想找到输入特征的平均值。输入是元组,如:

('phone_number', '123')
('phone_number', '456')
('phone_number', '456')
('phone_number', '456')
管道的第一部分是计算每个数字的频率:

| 'window' >> beam.WindowInto(window.SlidingWindows(900, 300))
| 'pair_with_one' >> beam.Map(lambda x: (x, 1))
| 'count_occurences' >> beam.combiners.Count.PerKey()
这是正确的。我的计算是正确的,我可以计算每个数字的频率,得到3个结果,因为每个时段有3个滑动窗口(在我们的案例中,456个呼叫中的2个在同一窗口中,第三个在不同的窗口中):

现在,我想找出所有计算的窗口值中每个电话号码的平均值,即:

(('phone_number', '123'), 1.0)
(('phone_number', '456'), 1.5)
我计划的下一步是

| 'Find Means' >> beam.combiners.Mean.PerKey()
但这只是给了我:

(('phone_number', '123'), 1.0)
(('phone_number', '123'), 1.0)
(('phone_number', '123'), 1.0)
(('phone_number', '456'), 2.0)
(('phone_number', '456'), 2.0)
(('phone_number', '456'), 2.0)
(('phone_number', '456'), 1.0)
(('phone_number', '456'), 1.0)
(('phone_number', '456'), 1.0)

是否有任何方法可以根据上一个beam.combiners的结果进行另一个beam.combiners计算?

beam.combiners.Mean.PerKey()给出错误输出的原因是,组合器为每个键+窗口提供了一个单独的计算值

然而,这里还有更多。流处理中窗口化的原因是为了确保在生成结果之前输入是有界的。也就是说,流式管道的输入通常是无界的,这意味着除非管道终止,否则它们永远不会停止接收数据。因此,不可能跨所有窗口计算一个值,因为您需要永远等待

在我看来,你似乎在试图计算“一个电话号码在15分钟窗口中的平均出现次数,当比较所有可能的15分钟滑动窗口时,每滑动5分钟一次”。如果不是这样,请澄清以帮助我理解

由于我们需要以某种方式绑定计算,因此可以周期性地输出结果,即对于每个窗口,并不断输出新结果,直到管道结束为止。这在StatefulDoFn中应该是可能的

为此,我建议:

  • 将滑动窗口中的计数输出到
  • 将总和和计数存储起来,以计算表中的平均值
  • 定期或在每个元素上输出计算的平均值,并在下游更新结果(即,在BigQuery中覆盖同一行,或在使用SQL检查BigQuery表时删除额外的行)
大概是这样的:

class ComputeMeanStatefulDoFn(DoFn):
  TOTAL_STATE = CombiningStateSpec('total', sum)
  COUNT_STATE = CombiningStateSpec('count', sum)

  def process(self, element,
      total=DoFn.StateParam(TOTAL_STATE),
      count=DoFn.StateParam(COUNT_STATE)):
    key_phone_number, value_window_count = element
    current_count = count.read() + 1
    current_total = total.read() + value_window_count
    mean = current_total / current_count
    # You can emit every N results to reduce the volume
    # but please make sure to at least emit the first M << N results
    yield (key_phone_number, mean)
    total.add(value_window_count)
    count.add(1)

| 'window' >> beam.WindowInto(window.SlidingWindows(900, 300))
| 'pair_with_one' >> beam.Map(lambda x: (x, 1))
| 'count_occurences' >> beam.combiners.Count.PerKey()
| 'window_globally' >> beam.WindowInto(window.GlobalWindows)
| 'compute_mean_across_windows' >> beam.ParDo(ComputeMeanStatefulDoFn)
类ComputeMeanStatefulDoFn(DoFn):
总计状态=组合状态规范(“总计”,总和)
COUNT\u STATE=CombiningStateSpec('COUNT',sum)
def过程(自身、元件、,
总计=DoFn.StateParam(总计状态),
count=DoFn.stateparm(count\u STATE)):
键\电话\号码、值\窗口\计数=元素
当前计数=计数。读取()+1
当前\u总计=总计.read()+值\u窗口\u计数
平均值=当前总数/当前计数
#可以每N个结果发射一次,以减少体积
#但请确保至少发射第一个M>光束.WindowInto(window.SlidingWindows(900300))
|'pair_with_one'>>beam.Map(lambda x:(x,1))
|“count\u occurrences'>>beam.combiners.count.PerKey()
|“window\u globally'>>beam.WindowInto(window.GlobalWindows)
|“跨窗口计算平均值”>>beam.ParDo(ComputeMeanStatefulDoFn)
本质上,这里发生的事情是,总和和计数被存储到persistence/disk,每当新元素到达全局窗口时,我们都会重新计算一个新的平均值

注意:您需要处理多次发送同一密钥的更新平均值。例如,您可能希望覆盖BigQuery表中包含您的结果的行

注意:根据您试图计算的语义,您可能希望从SlidingWindows函数发出空窗口,以便将它们包括在下游平均值计算中


注意:此处不能全局使用Combine.global,因为这永远不会终止,因为流式管道中的输入是无限的。我相信如果您尝试启动这样的管道,这可能会出错。

beam.combiners.Mean.PerKey()给您的输出不正确,原因是combiner给您的是为每个键+窗口计算的单个值

然而,这里还有更多。流处理中窗口化的原因是为了确保在生成结果之前输入是有界的。也就是说,流式管道的输入通常是无界的,这意味着除非管道终止,否则它们永远不会停止接收数据。因此,不可能跨所有窗口计算一个值,因为您需要永远等待

在我看来,你似乎在试图计算“一个电话号码在15分钟窗口中的平均出现次数,当比较所有可能的15分钟滑动窗口时,每滑动5分钟一次”。如果不是这样,请澄清以帮助我理解

由于我们需要以某种方式绑定计算,因此可以周期性地输出结果,即对于每个窗口,并不断输出新结果,直到管道结束为止。这在StatefulDoFn中应该是可能的

为此,我建议:

  • 将滑动窗口中的计数输出到
  • 将总和和计数存储起来,以计算表中的平均值
  • 定期或在每个元素上输出计算的平均值,并在下游更新结果(即,在BigQuery中覆盖同一行,或在使用SQL检查BigQuery表时删除额外的行)
大概是这样的:

class ComputeMeanStatefulDoFn(DoFn):
  TOTAL_STATE = CombiningStateSpec('total', sum)
  COUNT_STATE = CombiningStateSpec('count', sum)

  def process(self, element,
      total=DoFn.StateParam(TOTAL_STATE),
      count=DoFn.StateParam(COUNT_STATE)):
    key_phone_number, value_window_count = element
    current_count = count.read() + 1
    current_total = total.read() + value_window_count
    mean = current_total / current_count
    # You can emit every N results to reduce the volume
    # but please make sure to at least emit the first M << N results
    yield (key_phone_number, mean)
    total.add(value_window_count)
    count.add(1)

| 'window' >> beam.WindowInto(window.SlidingWindows(900, 300))
| 'pair_with_one' >> beam.Map(lambda x: (x, 1))
| 'count_occurences' >> beam.combiners.Count.PerKey()
| 'window_globally' >> beam.WindowInto(window.GlobalWindows)
| 'compute_mean_across_windows' >> beam.ParDo(ComputeMeanStatefulDoFn)
类ComputeMeanStatefulDoFn(DoFn):
总计状态=组合状态规范(“总计”,总和)
COUNT\u STATE=CombiningStateSpec('COUNT',sum)
def过程(自身、元件、,
总计=DoFn.StateParam(总计状态),
count=DoFn.stateparm(count\u STATE)):
键\电话\号码、值\窗口\计数=元素
当前计数=count.read