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-有没有办法加快速度^^