【问题标题】:count words in string element in a tab delimited file在制表符分隔的文件中计算字符串元素中的单词
【发布时间】:2017-11-04 10:56:17
【问题描述】:

我有一个制表符分隔的文本文件。我需要提取第二个元素,并且只对出现在第二个元素中的单词进行字数统计。 (我还需要过滤少于 3 个字符的单词,并希望将单词显示为键并按计数的降序计数作为值。)

我可以使用读取文件

scala> val lines = sc.textFile("MYDIR/myfile").map(_.split("\t"))

scala> lines.take(3) 

我得到Array[Array[String]] =

Array(Array(abc, Here is the First Text, en, Thu Sep 26 08:25:42 CDT 2013, null),
      Array(def, and here is the Second text, en, Thu Sep 26 08:27:22 CDT 2013, null),
      Array(ghi, and here is Another text, en, Thu Sep 26 08:50:21 CDT 2013, null))

如果我映射得到第二个元素

val wrdStr = lines.map(ar=>ar(1).toLowerCase)

wrdStr.take(3)
Array[String] = Array(here is the first text, and here is the second text, and here is Another text)

我想做基本的字数统计,但是如果我.flatMap(_.split("\\W+")),并在每个单词中添加 ,1,我就不再有 RDD,所以当我尝试执行 reduce 操作时它会失败。如何实现字数统计?一旦我映射到第二个元素?

【问题讨论】:

  • Arrayreduce 操作相同RDD,你可以做arrayStr.reduce(_ + _).split(" ").size
  • 你能再扩展一点吗?谢谢
  • 实际上如果没有明确的问题陈述很难解释。 Array(here is the first text(我的代码 sn-p 中的arrayStr)可以很容易地简化为一个字符串(使用reduce),这几乎可以回答您的标题问题。
  • 但是如果您使用 Spark,您可能必须关心可伸缩性,因此最好还是使用 RDD,正如 Ramesh Maharjan 指出的那样。否则使用 Spark 读取文件是没有意义的——你可以使用常规的scala.io.Source API。简单地说:如果文件很小(适合 RAM),则根本没有理由使用 Spark。
  • 谢谢,这很有道理!

标签: arrays string scala apache-spark


【解决方案1】:

您可以执行以下操作

wrdStr.flatMap(line => line.split("\\W+"))
    .filter(word => word.length > 2)
    .map(word => (word, 1))
    .reduceByKey(_ + _)
    .sortBy(x => x._2, ascending = false)
    .foreach(println)

你应该有以下输出

(text,3)
(here,3)
(and,2)
(the,2)
(second,1)
(another,1)
(first,1)

【讨论】:

  • 这对我不起作用。如果我一步一步地做,我可以到 wrdStr.flatMap(line => line.split("\\W+")).filter(word => word.length > 2).map(word => (word, 1)) 但是reduce失败 wrdStr.reduceByKey(_ + ) :32: error: value reduceByKey is not a member of org.apache.spark.rdd.RDD[String] wrdStr.reduceByKey( + _)
  • 它应该是 .reduceByKey(_ + _) 而不是 .reduceByKey(_ + ) 。你错过了结局_
  • 这里只是一个错字。我在 scala> 提示符下正确了..... scala> val wrdStr = lines.map(ar=>ar(1).toLowerCase) wrdStr: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[ 6] 在地图 :29 scala> wrdStr.flatMap(line => line.split("\\W+")).filter(word => word.length > 2).map(word => (word , 1)) res1: org.apache.spark.rdd.RDD[(String, Int)] = MapPartitionsRDD[9] at map at :32 scala> wrdStr.reduceByKey(_ + ) :32: 错误:值 reduceByKey 不是 org.apache.spark.rdd.RDD[String] wrdStr.reduceByKey( + _) 的成员
  • scala> wrdStr.reduceByKey(_ + _) <console>:32: error: value reduceByKey is not a member of org.apache.spark.rdd.RDD[String] wrdStr.reduceByKey(_ + _) ^
  • 为什么要在单独的行上应用 reduceByKey ?它应该应用于转换后的 (k,v) 而不是 wrdStr。请像我在答案中所做的那样使用它。 :)
猜你喜欢
  • 2012-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
相关资源
最近更新 更多