背景: 挖掘重要的关键词
问题:数据量较大(百万量级),单机版的python虽然处理起来简单,但是时间较长,内存是否溢出还不好说(看机器性能)
解决方案: spark 分布式处理
原始数据: 一个txt文件,文件格式每一行都是去停用词、分词之后的句子
代码如下:
import org.apache.spark.ml.feature.{HashingTF,IDF,Tokenizer}
val data = sc.textFile(file_path + "xx.txt").toDF("sentence")
val tokenizer = new Tokenizer().setInputCol("sentence").setOutputCol("words")
val wordsData = tokenizer.transform(data)
val hashingTF = new HashingTF().setInputCol("words").setOutputCol("rawFeatures")
val featurizedData = hashingTF.transform(wordsData)
val idf = new IDF().setInputCol("rawFeatures").setOutputCol("features")
val idfModel = idf.fit(featurizedData)
val rescaledData = idfModel.transform(featurizedData)
val d1 = rescaledData.select("words","features")
val d2 = d1.select(col("words"),col("features").cast("string"))
val Df2 = d2.withColumn("features_1",split(col("features"), "],")).select(
col("words"),
col("features_1").getItem(0).as("col1"),
col("features_1").getItem(1).as("col2")
)
val code = (sentence: String) => {
sentence.replace("[","").replace("]","").replace(")","")
}
val addCol = udf(code)
val DF3 = Df2.withColumn("col3", addCol(Df2("col2")))
val DF4 = DF3.select(col("words").cast("string"),col("col3"))
val DF5 = DF4.withColumn("words_",addCol(DF4("words")))
val DF6 = DF5.select("words_","col3")
DF6.createOrReplaceTempView("aa")
val DF7 = spark.sql("select words_,col3,single_id,single_tim from aa lateral view posexplode(split(words_,',')) t as single_id_index,single_id lateral view posexplode(split(col3,',')) t as single_tim_index,single_tim where single_id_index = single_tim_index")
val DF8 = DF7.select(col("single_id"),col("single_tim").cast("Double"))
val DF9 = DF8.groupBy("single_id").sum("single_tim")
val DF10 = DF9.sort(DF9("sum(single_tim)").desc)
DF10.show(5000)
巧妙的应用点:
1、应用udf函数
2、在DF6变量的时候,存在一个两列字符串,需要将字符串中的词与另一个字符串中的相同位置的值进行对应,并且每行的句子个数还不一样,如果将spark Dataframe 格式数据转化成.rdd.map{...}后续操作比较麻烦,用到hive的窗口函数posexplode是一个多行转多列的方法,而且还可以找到index,大大提高了效率
缺点: 代码没有整理,看着有点乱