将随机样本从一个火花数据帧添加到另一个

时间:2017-06-13 23:53:06

标签: python apache-spark pyspark pyspark-sql

我有两个这样的数据框:

| User |
 ------
| 1    |
| 2    |
| 3    |

| Articles |
 ----------
| 'A'      |
| 'B'      |
| 'C'      |

什么是随机分配每个用户2 articles的直观方式? 输出数据框可能如下所示:

| User | Articles |
 -----------------
| 1    | 'A'      |
| 1    | 'C'      |
| 2    | 'C'      |
| 2    | 'B'      |
| 3    | 'C'      |
| 3    | 'A'      |

以下是生成这两个数据帧的代码:

u =[(1,), (2,), (3,)]
rdd = sc.parallelize(u)
users = rdd.map(lambda x: Row(user_id=x[0]))
users_df = sqlContext.createDataFrame(users)

a = [('A',), ('B',), ('C',), ('D',), ('E',)]
rdd = sc.parallelize(a)
articles = rdd.map(lambda x: Row(article_id=x[0]))
articles_df = sqlContext.createDataFrame(articles)

1 个答案:

答案 0 :(得分:0)

由于您的文章列表很小,因此将其保留为python对象而不是分布式列表是有意义的。这将允许您创建一个udf来为每个user_id生成一个随机的文章列表。以下是您可以这样做的一种方式:

from random import sample,seed
from pyspark.sql import Row
from pyspark.sql.functions import udf,explode
from pyspark.sql.types import ArrayType,StringType

class ArticleRandomizer(object):
    def __init__(self,article_list,num_articles=2,preseed=0):
        self.article_list=article_list
        self.num_articles=num_articles
        self.preseed=preseed
    def getrandom(self,user):
        seed(user+self.preseed)
        return sample(self.article_list,self.num_articles)

u =[(1,), (2,), (3,)]
rdd = sc.parallelize(u)
users = rdd.map(lambda x: Row(user_id=x[0]))
users_df = sqlContext.createDataFrame(users)

a = [('A',), ('B',), ('C',), ('D',), ('E',)]
#rdd = sc.parallelize(a)
#articles = rdd.map(lambda x: Row(article_id=x[0]))
#articles_df = sqlContext.createDataFrame(articles)

article_list=[article[0] for article in a]
ARandomizer=ArticleRandomizer(article_list)
add_articles=udf(ARandomizer.getrandom,ArrayType(StringType()))
users_df.select('user_id',explode(add_articles('user_id'))).show()

ArticleRandomizer.getrandom函数由user_id播种,因此它是确定性的,这意味着您将为每次运行获得给定用户的相同随机文章列表。您可以通过在实例化类时更改preseed值来调整此值以获取可能不同的列表。

尚未对此进行测试以确定它是否可以很好地扩展,但它应该可以在数据集上正常工作,因为文章和用户的维度都相当小。

相关问题