我是Spark的初学者。我正在使用Pyspark将我的遗留Python代码转换为Spark。
我想获得与下面代码相当的Pyspark
usersofinterest = actdataall[actdataall['ORDValue'].isin(orddata['ORDER_ID'].unique())]['User ID']
actdataall
和orddata
都是Spark数据帧。
我不想使用toPandas()
函数给出与之相关的缺点。
感谢任何帮助。
答案 0 :(得分:2)
如果两个数据帧都很大,您应该考虑使用内部联接作为过滤器:
首先让我们创建一个包含我们要保留的订单ID的数据框:
orderid_df = orddata.select(orddata.ORDER_ID.alias("ORDValue")).distinct()
现在让我们加入我们的actdataall数据框:
usersofinterest = actdataall.join(orderid_df, "ORDValue", "inner").select('User ID').distinct()
如果您的目标订单ID列表很小,那么您可以使用furianpandit帖子中提到的pyspark.sql isin函数,不要忘记在使用之前广播您的变量(spark会将对象复制到每个节点使他们的任务更快):
orderid_list = orddata.select('ORDER_ID').distinct().rdd.flatMap(lambda x:x).collect()[0]
sc.broadcast(orderid_list)
答案 1 :(得分:1)
您的代码的最直接翻译将是:
from pyspark.sql import functions as F
# collect all the unique ORDER_IDs to the driver
order_ids = [x.ORDER_ID for x in orddata.select('ORDER_ID').distinct().collect()]
# filter ORDValue column by list of order_ids, then select only User ID column
usersofinterest = actdataall.filter(F.col('ORDValue').isin(order_ids)).select('User ID')
但是,只有当'ORDER_ID'的数量肯定很小(可能<100,000左右)时,才应该像这样过滤。
如果'ORDER_ID'的数量很大,你应该使用一个广播变量,它将order_id列表发送给每个执行者,这样它就可以在本地与order_ids进行比较,以便加快处理速度。请注意,即使'ORDER_ID'很小,这也会有效。
order_ids = [x.ORDER_ID for x in orddata.select('ORDER_ID').distinct().collect()]
order_ids_broadcast = sc.broadcast(order_ids) # send to broadcast variable
usersofinterest = actdataall.filter(F.col('ORDValue').isin(order_ids_broadcast.value)).select('User ID')
有关广播变量的更多信息,请查看:https://jaceklaskowski.gitbooks.io/mastering-apache-spark/spark-broadcast.html
答案 2 :(得分:0)
所以,你有两个火花数据帧。一个是actdataall,另一个是orddata,然后使用以下命令来获得你想要的结果。
usersofinterest = actdataall.where(actdataall['ORDValue'].isin(orddata.select('ORDER_ID').distinct().rdd.flatMap(lambda x:x).collect()[0])).select('User ID')