Pyspark 分组记录后计算单词数

Pyspark 分组记录后计算单词数,pyspark,Pyspark,注意:尽管提供的答案有效,但在较大的数据集上可能会变得相当缓慢。以获得更快的解决方案 我有一个数据框,它由带标签的文档组成,例如: df_979;=spark.createDataFrame([ (“1”,“你好,今天好吗”), (‘1’、‘你好’), (“2”,“你好,你在吗”), (‘2’、‘怎么样’), (‘3’、‘你好’), (‘3’、‘你好’), (‘4’、‘你好,今天怎么样’) ],schema=['label','text']) 我想要的是按label对数据帧进行分组,并对每组

注意:尽管提供的答案有效,但在较大的数据集上可能会变得相当缓慢。以获得更快的解决方案


我有一个数据框,它由带标签的文档组成,例如:

df_979;=spark.createDataFrame([
(“1”,“你好,今天好吗”),
(‘1’、‘你好’),
(“2”,“你好,你在吗”),
(‘2’、‘怎么样’),
(‘3’、‘你好’),
(‘3’、‘你好’),
(‘4’、‘你好,今天怎么样’)
],schema=['label','text'])
我想要的是按
label
对数据帧进行分组,并对每组进行简单的字数统计。我的问题是我不确定如何在PySpark中做到这一点。在第一步中,我将拆分文本并将文档作为令牌列表获取:

def get_token_计数(文本):
如果文本为无:
返回列表()
计数器=计数器(text.lower().split())
返回列表(counter.items())
udf\u获取令牌\u计数=F.udf(获取令牌\u计数)
df_u.select(['label']+[udf_get_令牌(F.col('text'))。别名('text')]))\
.show()
给予

+-----+--------------------+
|label|                text|
+-----+--------------------+
|    1|[hello, how, are,...|
|    1|[hello, how, are,...|
|    2|[hello, are, you,...|
|    2|[hello, how, is, it]|
|    3|[hello, how, are,...|
|    3|[hello, how, are,...|
|    4|[hello, how, is, ...|
+-----+--------------------+
我知道如何在整个数据帧中计算字数,但我不知道如何继续执行
groupby()
reducebykey()

我在考虑部分计算数据框中的单词:

df_u.select(['label']+[udf_get_令牌(F.col('text'))。别名('text'))\
.rdd.map(lambda x:(x[0],list(Counter(x[1]).items())\
.toDF(架构=['label','text'])\
.show()
其中:

+-----+--------------------+
|label|                text|
+-----+--------------------+
|    1|[[are,2], [hello,...|
|    1|[[are,1], [hello,...|
|    2|[[are,1], [hello,...|
|    2|[[how,1], [it,1],...|
|    3|[[are,1], [hello,...|
|    3|[[are,1], [hello,...|
|    4|[[you,1], [today,...|
+-----+--------------------+
但是我如何聚合这些内容呢?

您应该使用拆分文本,而不是使用
udf
。(此外,根据您所做的工作,您可能会发现这是有用的。)

例如:

来自pyspark.ml.feature导入标记器
标记器=标记器(inputCol=“text”,outputCol=“标记”)
tokens=tokenizer.transform(df_41;
tokens.show(truncate=False)
+-----+---------------------------+----------------------------------+
|标签|文本|标记|
+-----+---------------------------+----------------------------------+
|你好,你好,你今天好吗|
|你好,你好吗|
|你好,你在吗|
|怎么样|
|你好,你好吗|
|你好,你好吗|
|你好,你今天怎么样|
+-----+---------------------------+----------------------------------+
然后,您可以选择标记,并执行
groupBy()
以获取每个单词的计数:

导入pyspark.sql.f函数
令牌计数=令牌。选择(“标签”,f.分解(“令牌”)。别名(“令牌”))\
.groupBy(“标签”、“令牌”).count()\
.orderBy(“标签”、“令牌”)
token_counts.show(truncate=False,n=10)
+-----+-----+-----+
|标签|令牌|计数|
+-----+-----+-----+
|1 |是| 3|
|1 |你好| 2|
|1 |如何| 2|
|1 |今天| 1|
|1 |你| 2|
|2 |是| 1|
|2 |你好| 1|
|2 |这里| 1|
|2 |如何| 1|
|2是1|
+-----+-----+-----+
仅显示前10行
如果您希望所有标记和计数在每个标签的一行上,只需使用另一个
groupBy()
,并使用以下方法连接
标记和
计数列:

tokens.选择(“标签”,f.explode(“标记”).别名(“标记”))\
.groupBy(“标签”、“令牌”)\
.count()\
.groupBy(“标签”)\
.agg(f.collect_list(f.struct(f.col(“token”)、f.col(“count”))。别名(“text”))\
.orderBy(“标签”)\
.show(truncate=False)
+-----+----------------------------------------------------------------+
|标签|文本|
+-----+----------------------------------------------------------------+
|1 |[[你好,2],[你好,2],[你好,3],[今天,1],[你,2]]|
|2 |[[你,1],[你好,1],[这里,1],[是,1],[它,1],[怎么样,1],[是,1]]|
|3 |[[你,2],[你好,2]]|
|4 |[今天,1],[你好,1],[它,1],[你,1],[你好,1],[是,1]]|
+-----+----------------------------------------------------------------+

Hmm。。不幸的是,这似乎相当缓慢。数据集大小约为50 GB-有没有办法加快速度^^