我有两个RDD说
rdd1 =
id | created | destroyed | price
1 | 1 | 2 | 10
2 | 1 | 5 | 11
3 | 2 | 3 | 11
4 | 3 | 4 | 12
5 | 3 | 5 | 11
rdd2 =
[1,2,3,4,5] # lets call these value as timestamps (ts)
rdd2基本上是使用range(intial_value,end_value,interval)生成的。这里的参数可以有所不同。大小可以与rdd1相同或不同。我的想法是使用过滤criertia基于rdd2的值从rdd1获取记录到rdd2(来自rdd1的记录可以在读取时重复,如输出中所示)
过滤标准rdd1.created< = ts< rdd1.destroyed)
预期产出:
ts | prices
1 | 10,11 # i.e. for ids 1,2 of rdd1
2 | 11,11 # ids 2,3
3 | 11,12,11 # ids 2,4,5
4 | 11,11 # ids 2,5
现在我想基于使用RDD2的键的某些条件来过滤RDD1。 (如上所述)并返回连接RDD2的键和RDD1的过滤结果的结果
所以我这样做:
rdd2.map(lambda x : somefilterfunction(x, rdd1))
def somefilterfunction(x, rdd1):
filtered_rdd1 = rdd1.filter(rdd1[1] <= x).filter(rdd1[2] > x)
prices = filtered_rdd1.map(lambda x : x[3])
res = prices.collect()
return (x, list(res))
我得到了:
例外:您似乎正在尝试广播RDD或 引用动作或转换中的RDD。 RDD转换 并且操作只能由驱动程序调用,而不能在其他内部调用 变换;例如,rdd1.map(lambda x:rdd2.values.count()* x)因为值转换和计数动作无效 无法在rdd1.map转换中执行。更多 信息,请参阅SPARK-5063。
我尝试使用groupBy,但是因为在这里rdd1的元素可以反复重复,因为与我理解的分组相比,rdd1的每个元素只能在某个特定的插槽中使用一次。
现在唯一的方法是使用普通for循环并进行过滤并最终加入所有内容。
任何建议?
答案 0 :(得分:4)
由于您使用常规范围,因此根本没有理由创建第二个RDD。您只需为每条记录生成特定范围内的值:
from __future__ import division # Required only for Python 2.x
from math import ceil
from itertools import takewhile
rdd1 = sc.parallelize([
(1, 1, 2, 10),
(2, 1, 5, 11),
(3, 2, 3, 11),
(4, 3, 4, 12),
(5, 3, 5, 11),
])
def generate(start, end, step):
def _generate(id, created, destroyed, price):
# Smallest ts >= created
start_for_record = int(ceil((created - start) / step) * step + start)
rng = takewhile(
lambda x: created <= x < destroyed,
xrange(start_for_record, end, step)) # In Python 3.x use range
for i in rng:
yield i, price
return _generate
result = rdd1.flatMap(lambda x: generate(1, 6, 1)(*x)).groupByKey()
结果:
result.mapValues(list).collect()
## [(1, [10, 11]), (2, [11, 11]), (3, [11, 12, 11]), (4, [11, 11])]