【问题标题】:Calculate TF-IDF grouped by column计算按列分组的 TF-IDF
【发布时间】:2018-11-09 14:31:08
【问题描述】:

如何计算 tf-idf 按列分组而不是在整个数据帧上?

假设在如下数据框中

private val sample = Seq(
    (1, "A B C D E"),
    (1, "B C D"),
    (1, "B C D E"),
    (2, "B C D F"),
    (2, "A B C"),
    (2, "B C E F G")
  ).toDF("id","sentences")

在上面的示例中,应通过考虑前三个元素来计算 id = 1 的句子的 IDF。同样的方式应该通过考虑最后三个元素来计算 IDF = 2 的句子。在 Spark ml 的 tf-idf 实现中是否有可能。

【问题讨论】:

  • 这样做有什么意义?
  • 我想删除每个 id 最少使用的单词。我也想得到每个 id 的常用词。基本上我想考虑基于id的TF-IDF计算。

标签: scala apache-spark apache-spark-sql apache-spark-mllib


【解决方案1】:

只是一个蹩脚的尝试:您可以通过 id 过滤序列并将每个过滤器转换为数据帧并将它们保存在列表中,然后使用循环将 tf-idf 应用于列表中的每个数据帧。

var filters=List[org.apache.spark.sql.DataFrame]()
val mySeq=Seq((1, "A B C D E"),(1, "B C D"),(1, "B C D E"),(2, "B C D F"),(2, "A B C"),(2, "B C E F G")) 
for(i<-List(1,2)){filters=filters:+s.filter{case x=>x._1==i}.toDF("id","sentences")}   

所以例如你有

scala> filters(0).show()
+---+---------+
| id|sentences|
+---+---------+
|  1|A B C D E|
|  1|    B C D|
|  1|  B C D E|
+---+---------+

scala> filters(1).show()
+---+---------+
| id|sentences|
+---+---------+
|  2|  B C D F|
|  2|    A B C|
|  2|B C E F G|
+---+---------+

您可以使用循环或map 对每个数据帧进行 TF-IDF 计算。

您也可以使用某种groupBy,但此操作需要随机播放,这可能会降低您在集群中的性能

【讨论】:

    【解决方案2】:

    您可以通过id 对数据帧进行分组,并在 TF-IDF 计算之前展平相应的标记化词。下面是使用来自Spark TF-IDF 文档的示例代码的 sn-p:

    val sample = Seq(
      (1, "A B C D E"),
      (1, "B C D"),
      (1, "B C D E"),
      (2, "B C D F"),
      (2, "A B C"),
      (2, "B C E F G")
    ).toDF("id","sentences")
    
    import org.apache.spark.sql.functions._
    import org.apache.spark.ml.feature.{HashingTF, IDF, Tokenizer}
    
    val tokenizer = new Tokenizer().setInputCol("sentences").setOutputCol("words")
    val wordsDF = tokenizer.transform(sample)
    
    def flattenWords = udf( (s: Seq[Seq[String]]) => s.flatMap(identity) )
    
    val groupedDF = wordsDF.groupBy("id").
      agg(flattenWords(collect_list("words")).as("grouped_words"))
    
    val hashingTF = new HashingTF().
      setInputCol("grouped_words").setOutputCol("rawFeatures").setNumFeatures(20)
    val featurizedData = hashingTF.transform(groupedDF)
    val idf = new IDF().setInputCol("rawFeatures").setOutputCol("features")
    val idfModel = idf.fit(featurizedData)
    val rescaledData = idfModel.transform(featurizedData)
    
    rescaledData.show
    // +---+--------------------+--------------------+--------------------+
    // | id|       grouped_words|         rawFeatures|            features|
    // +---+--------------------+--------------------+--------------------+
    // |  1|[a, b, c, d, e, b...|(20,[1,2,10,14,18...|(20,[1,2,10,14,18...|
    // |  2|[b, c, d, f, a, b...|(20,[1,2,8,10,14,...|(20,[1,2,8,10,14,...|
    // +---+--------------------+--------------------+--------------------+
    

    【讨论】:

      猜你喜欢
      • 2019-01-10
      • 1970-01-01
      • 2012-04-23
      • 2015-04-17
      • 2017-03-07
      • 2017-11-14
      • 1970-01-01
      • 2021-06-17
      • 2014-04-21
      相关资源
      最近更新 更多