Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.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 pyspark:根据另一个RDD的某些列过滤一个RDD_Python_Apache Spark_Mapreduce_Pyspark - Fatal编程技术网

Python pyspark:根据另一个RDD的某些列过滤一个RDD

Python pyspark:根据另一个RDD的某些列过滤一个RDD,python,apache-spark,mapreduce,pyspark,Python,Apache Spark,Mapreduce,Pyspark,我在spark集群中有两个文件,foo.csv和bar.csv,都有4列和相同的字段: 时间、用户、url、类别 我想通过bar.csv的某些列过滤掉foo.csv。最后,我需要(用户、类别):[list、of、url]的键/值对。例如: foo.csv: 11:50:00, 111, www.google.com, search 11:50:00, 222, www.espn.com, news 11:50:00, 333, www.reddit.com, news 11:50:00, 444

我在spark集群中有两个文件,
foo.csv
bar.csv
,都有4列和相同的字段:
时间、用户、url、类别

我想通过
bar.csv
的某些列过滤掉
foo.csv
。最后,我需要(用户、类别):[list、of、url]的键/值对。例如:

foo.csv:
11:50:00, 111, www.google.com, search
11:50:00, 222, www.espn.com, news
11:50:00, 333, www.reddit.com, news
11:50:00, 444, www.amazon.com, store
11:50:00, 111, www.bing.com, search
11:50:00, 222, www.cnn.com, news
11:50:00, 333, www.aol.com, news
11:50:00, 444, www.jet.com, store
11:50:00, 111, www.yahoo.com, search
11:50:00, 222, www.bbc.com, news
11:50:00, 333, www.nytimes.com, news
11:50:00, 444, www.macys.com, store

bar.csv:
11:50:00, 222, www.bbc.com, news
11:50:00, 444, www.yahoo.com, store
应导致:

{
(111, search):[www.google.com, www.bing.com, www.yahoo.com],
(333, news): [www.reddit.com, www.aol.com, www.nytimes.com]
}
换句话说,如果
bar.csv
中存在(用户、类别)对,我想过滤掉
foo.csv
中的所有行,如果它们有相同的(用户、类别)对。因此,在上面的示例中,我想用
(222,新闻)
(444,商店)
删除
foo.csv
中的所有行。最后,在删除我想要的行之后,我想要一个具有键/值对的字典,如:
(用户,类别):[list,of,url]

这是我的密码:

fooRdd = sc.textFile("file:///foo.txt/")
barRdd = sc.textFile("file:///bar.txt/")


parseFooRdd= fooRdd.map(lambda line: line.split(", "))
parseBarRdd = barRdd.map(lambda line: line.split(", "))



# (n[1] = user_id, n[3] = category_id) --> [n[2] = url]
fooGroupRdd = parseFooRdd.map(lambda n: ((n[1], n[3]), n[2])).groupByKey().map(lambda x: {x[0]: list(x[1])})
barGroupRdd = parseBarRdd.map(lambda n: ((n[1], n[3]), n[2])).groupByKey().map(lambda x: {x[0]: list(x[1])})
上面的代码可以工作,并以我想要的格式获取数据集:

(user_id, category): [all, urls, visited, by, user, in, that, category]

然而,有两个问题:1)我认为它会返回一个字典列表,其中只有一个k/v对;2)我无法确定下一步该做什么。我知道用英语该怎么做:在
barGroupRdd
(tuples)中获取键,然后删除fooGroupRdd中具有相同键的所有行。但我是pyspark的新手,我觉得有些命令我没有利用。我认为我的代码可以优化。例如,我认为我不需要创建
barGroupRdd
行,因为我从
bar.csv
需要的只是(用户id,类别)——我不需要创建字典。我还认为我应该先过滤掉,然后根据结果创建字典。任何帮助或建议都将不胜感激,谢谢

你真的很接近

而不是针对每个RDD:

fooGroupRdd = parseFooRdd.map(lambda n: ((n[1], n[3]),\
    n[2])).groupByKey().map(lambda x: {x[0]: list(x[1])})
这样做:

fooGroupRdd = parseFooRdd.map(lambda n: ((n[1], n[3]),\
    n[2])).groupByKey().map(lambda x: [(x[0]), list(x[1])])
这样,您就可以使用rdd.keys()方法访问密钥,并创建一个
bar\u-keys
列表

bar_keys = barGroupRdd.keys().collect()
然后你就可以照你说的做了。筛选FoodGroupRDD中具有键的行

dict(fooGroupRdd.filter(lambda x: x[0] not in bar_keys)\
    .map(lambda x: [x[0], x[1]]).collect())
最终结果如下所示:

{('111', 'search'): ['www.google.com', 'www.bing.com', 'www.yahoo.com'],
 ('333', 'news'): ['www.reddit.com', 'www.aol.com', 'www.nytimes.com']}
希望有帮助


根据你的评论,我也想知道这是否是最有效的方法。查看RDD的类方法,您会发现
collectAsMap()
,它与collect类似,但返回的是字典而不是列表。然而,在对源代码进行调查后,该方法与我所做的完全相同,因此这似乎是最好的选择。

谢谢,成功了!感觉API中有很多spark函数对我来说都是新的,我希望这是最有效的解决方案。第一次替换真的帮助了我,再一次,非常感谢。