Apache spark 分组记录后的字数计算(第2部分)
虽然我支持我想要实现的目标,但问题是这是一种缓慢的方式。数据集不是很大。总共是50GB,但受影响的部分可能只有5到10GB的数据。然而,以下是我所需要的,但这是一种缓慢的方式,我所说的缓慢是指它运行了一个小时,并没有终止 df_u3;=spark.createDataFrame[ “你好,今天好吗?”, “1”,“你好吗”, “2”,“你好,你在吗”, “2”,“怎么样”, “3”,“你好”, “3”,“你好”, “4”,“你好,你今天好吗” ],schema=['label','text'] tokenizer=TokenizerinputCol='text',outputCol='tokens' tokens=tokenizer.transformdf_ token_计数。groupby'label'\ .aggF.collect_listF.structF.col'token',F.col'count'。别名'text'\ .showtruncate=False 这为我提供了每个标签的令牌计数:Apache spark 分组记录后的字数计算(第2部分),apache-spark,pyspark,Apache Spark,Pyspark,虽然我支持我想要实现的目标,但问题是这是一种缓慢的方式。数据集不是很大。总共是50GB,但受影响的部分可能只有5到10GB的数据。然而,以下是我所需要的,但这是一种缓慢的方式,我所说的缓慢是指它运行了一个小时,并没有终止 df_u3;=spark.createDataFrame[ “你好,今天好吗?”, “1”,“你好吗”, “2”,“你好,你在吗”, “2”,“怎么样”, “3”,“你好”, “3”,“你好”, “4”,“你好,你今天好吗” ],schema=['label','text']
+-----+----------------------------------------------------------------+
|label|text |
+-----+----------------------------------------------------------------+
|3 |[[are,2], [how,2], [hello,2], [you,2]] |
|1 |[[today,1], [how,2], [are,3], [you,2], [hello,2]] |
|4 |[[hello,1], [how,1], [is,1], [today,1], [you,1], [it,1]] |
|2 |[[hello,1], [are,1], [you,1], [here,1], [is,1], [how,1], [it,1]]|
+-----+----------------------------------------------------------------+
然而,我认为对这个来说,要求爆炸的代价太高了
我不知道,但计算每个dokument中的令牌数,然后将其合并到groupBy中可能会更快:
df_u.select['label']+[udf_get_tokensF.col'text'。别名'text']\
.rdd.maplambda x:x[0],listCounterx[1]。项\
.toDFschema=['label','text']\
显示
给出了计数:
+-----+--------------------+
|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,...|
+-----+--------------------+
有没有一种方法可以更有效地合并这些令牌计数?如果由id定义的组更大,那么改进的明显目标就是洗牌大小。洗牌标签,而不是洗牌文本。第一矢量化输入
从pyspark.ml.feature导入CountVectorizer
从pyspark.ml导入管道
管道\模型=管道阶段=[
TokenizerinputCol='text',outputCol='tokens',
CountVectorierInputCol='tokens',outputCol='vectors'
]fitdf先生_
df\u vec=管道模型。转换df\ux。选择标签,向量
然后汇总:
从pyspark.ml.linalg导入SparseVector、DenseVector
从集合导入defaultdict
def seq_funcacc,v:
如果isinstancev,SparseVector:
对于i/v指数:
acc[inti]+=v[inti]
如果是安装,则DenseVector:
对于lenv中的i:
acc[inti]+=v[inti]
返回acc
def comb_funcacc1、acc2:
对于acc2.1项目中的k、v:
acc1[k]+=v
返回acc1
聚合=rdd.aggregateByKeyDefaultDictent,seq_func,comb_func
并映射回所需的输出:
词汇表=管道模型。阶段[-1]。词汇表
def fx,词汇=词汇:
对于元组列表,使用[词汇表[i],floatv表示i,v表示x.items]
返回{词汇表[i]:floatv表示i,v表示x.items}
聚合的.mapValuesf.toDF[id,文本].showtruncate=False
+--+-------------------------------------------+
|id |文本|
+--+-------------------------------------------+
|4 |[如何->1.0,今天->1.0,是->1.0,它->1.0,你好->1.0,你->1.0]|
|3 |[如何->2.0,你好->2.0,是->2.0,你->2.0]|
|1 |[如何->2.0,你好->2.0,是->3.0,你->2.0,今天->1.0]|
|2 |[这里->1.0,如何->1.0,是->1.0,是->1.0,它->1.0,你好->1.0,你->1.0]|
+--+-------------------------------------------+
只有在文本部分相当大的情况下才值得尝试,否则DataFrame和Python对象之间所有必需的转换可能比收集列表更昂贵。Hi!谢谢你的回答!不幸的是,我只能在下周的星期二测试它,但我不会忘记接受它:很抱歉反应太晚-直到今天我才有时间继续进行这方面的工作。你的答案绝对比爆炸版快!非常感谢。