如何在Scala中进行数据清理

时间:2016-07-17 19:17:01

标签: scala hadoop apache-spark

我刚开始使用Spark上的Scala,所以我不确定我的问题是否可行或者我应该转向其他解决方案/工具:

我有一个用于字数统计和排序的文本文件,这里是file

  1. 我将文件加载到HDFS
  2. 然后我在Scala中使用以下代码进行计数:

    val file = sc.textFile("hdfs://localhost:9000/Peter")
    val counts = file.flatMap(line => line.split(" ")).map(p => (p,1)).reduceByKey(_+_).sortByKey(true,1)
    counts.saveAsTextFile("Peter_SortedOutput6")
    
  3. 我通过hdfs dfs -cat hdfs://localhost:9000/user/root/Peter_SortedOutput5/part-00000
  4. 检查了hdfs上的结果

    为方便阅读,部分结果发布在此处:

      

    ((因为,1)   ((没有,1)   (1,8)   (10,8)   (11,8)   (12,8)   (13,8)   (14,8)   (15,7)   (16,7)   (17,7)   (18,7)   (19,6)   (2,8)   (20,5)   (21,5)   (22,4)   (23,2)   (24,2)   (25,2)   (3,8)   (4,8)   (5,8)   (6,8)   (7,8)   (8,8)   (9,8)   (亚伯拉罕,, 1)   (据,1)   (阿门。,4)   (而且,19)   (如,5)   (亚洲,, 1)   (巴比伦,, 1)   (巴兰,1)   (成为,2)   (因为,1)

    首先,这真的不是我所期望的,我希望结果以计数的desc顺序显示。 其次,结果如下:

      

    (神,25)   (神' S,1)   (神,, 9)   (神,),1)   (神。,6)   (神:,2)   (神;,2)   (神?,1)

    如何在分裂中进行一些清洁,以便将这些事件分组为一个(上帝,47)

    非常感谢。

2 个答案:

答案 0 :(得分:1)

Berkerly& Databricks在edx.org上有一个BerkeleyX: CS105x Introduction to Apache Spark课程。其中一项任务是进行字数统计。

步骤

  • 删除标点符号,将“[^ A-Za-z0-9 \ s] +”替换为“”,或者不包含数字“[^ A-Za-z \ s] +”
  • 修剪所有空格
  • 降低所有单词

我们可以添加额外的步骤,如

  • 删除停用词

代码如下

import org.apache.spark.ml.feature.StopWordsRemover
import org.apache.spark.sql.functions.split

// val reg = raw"[^A-Za-z0-9\s]+" // with numbers

val reg = raw"[^A-Za-z\s]+" // no numbers
val lines = sc.textFile("peter.txt").
    map(_.replaceAll(reg, "").trim.toLowerCase).toDF("line")
val words = lines.select(split($"line", " ").alias("words"))

val remover = new StopWordsRemover()
      .setInputCol("words")
      .setOutputCol("filtered")

val noStopWords = remover.transform(words)

val counts = noStopWords.select(explode($"filtered")).map(word =>(word, 1))
    .reduceByKey(_+_)

// from word -> num to num -> word
val mostCommon = counts.map(p => (p._2, p._1)).sortByKey(false, 1)

mostCommon.take(5)

答案 1 :(得分:0)

使用replaceAll清理数据:

val counts = file.flatMap(line => line.trim.toLowerCase.split(" ").replaceAll("[$,?+.;:\'s\\W\\d]", ""));

在scala API中按值排序:

.map(item => item.swap) // interchanges position of entries in each tuple
.sortByKey(true, 1) // 1st arg configures ascending sort, 2nd arg configures one task
.map(item => item.swap)

在python API中按值排序:

.map(lambda (a, b): (b, a)) \
.sortByKey(1, 1) \ # 1st arg configures ascending sort, 2nd configures 1 task
.map(lambda (a, b): (b, a))

代码应如下所示(您可能会看到语法错误,请修复,如果有的话):

val file = sc.textFile("hdfs://localhost:9000/Peter")
val counts = file.flatMap(line => line.trim.toLowerCase.split(" ").replaceAll("[$,?+.;:\'s\\W\\d]", ""))
                 .map(p => (p,1))
                 .reduceByKey(_+_)
                 .map(rec => rec.swap)
                 .sortByKey(true, 1)
                 .map(rec => rec.swap)

counts.saveAsTextFile("Peter_SortedOutput6")

请参阅scala_regular_expressions - 了解[\\W][\\d][;:',.?]的含义。