将RDD转换为广播词典以进行查找

时间:2015-10-15 20:30:27

标签: python apache-spark

到目前为止我所拥有的是:

lookup = sc.textFile("/user/myuser/lookup.asv")
lookup.map(lambda r: r.split(chr(1)) )

现在我的RDD看起来像

[
    [filename1, category1],
    [filename2, category2],
    ...
    [filenamen, categoryn]
]

如何将该RDD转换为广播词典,如:

{filename1: category1, filename2: category2, ...}

这是我尝试但不工作的原因:

>>> broadcastVar = sc.broadcast({})
>>> data = sc.parallelize([[1,1], [2,2], [3,3], [4,4]])
>>> def myfunc(x):
...     broadcastVar[str(x[0])] = x[1]
... 
>>> result = data.map(myfunc)
>>> broadcastVar
<pyspark.broadcast.Broadcast object at 0x7f776555e710>
>>> broadcastVar.value
{}
>>> result.collect()
...
ERROR: TypeError: 'Broadcast' object does not support item assignment
...
>>> broadcastVar.value
{}

有关我为什么要构建这个巨大的查找变量的更多信息,请阅读:

这是one的后续问题。

我有两张表

table1:一个非常宽的(25K列和150K行)表,其中每列包含像素信息,第一列是输入图像文件的文件名。

table2:TSV(制表符分隔文件)文件,有300万行,每行包含图像文件名和图像的产品类别。

在SQL中,我需要对文件名上的这两个表进行内部联接,这样我就可以标记图像数据,以便以后在机器学习上使用。

在任何类型的SQL中执行它是不现实的,因为你必须为table1创建一个具有25K列的表,create table语法将是荒谬的。

然后我考虑使用table2创建一个查找变量,并可能使它成为一个广播变量,其中键是文件名,值是产品类别。

1 个答案:

答案 0 :(得分:0)

广播变量对工人是只读的。 Spark提供只写的累加器,但这些累积器用于计数器之类的东西。在这里,您可以简单地收集和创建Python字典:

    <script type="text/javascript" src="Scripts/jasmine.js"></script>
    <script type="text/javascript" src="Scripts/jasmine-html.js"></script>
    <script type="text/javascript" src="Scripts/boot.js"></script>

    <script type="text/javascript" src="Scripts/require.js"></script>

    <script type="text/javascript">
    require.config({
      paths: {
        "jquery": './Scripts/jquery-1.10.2.min',
        "knockout": './Scripts/knockout.debug', 
        "testViewModel" :"./Scripts/viewmodel",
      }
    });
    // list spec files here
    require(["knockout","jquery","specs/someSpec", "testViewModel"], function () {
        window.onload();
    });
</script>
  

在任何类型的SQL中执行它是不现实的,因为你必须为table1创建一个具有25K列的表,create table语法将是荒谬的。

创造应该不是问题。只要您知道名称,就可以通过编程方式轻松创建表格:

lookup_bd = sc.broadcast({
  k: v for (k, v) in lookup.map(lambda r: r.split(chr(1))).collect()
})

这里还有另一个问题,即使你使用普通的RDD也要严重得多。非常宽的行通常难以以任何行方式处理。

您可以做的一件事是使用稀疏表示,如from pyspark.sql import Row colnames = ["x{0}".format(i) for i in range(25000)] # Replace with actual names df = sc.parallelize([ row(*[randint(0, 100) for _ in range(25000)]) for x in range(10) ]).toDF() ## len(df.columns) ## 25000 SparseVector。另一种方法是使用RLE编码像素信息。