如何为RDD / Dataframe中的整行创建sha1散列

时间:2017-09-12 10:20:47

标签: scala apache-spark

我有一个带有一个架构的数据框。现有数据框已经有50列。现在我想在现有数据框中添加一个新列。新列名是" hashing_id"并且此hashing_id的逻辑是sha1(行)。我怎么做到这一点?

我尝试了以下代码。以下两种方法都在主类中使用的特征内。这个特性也扩展了Serializable

 def addHashingKey():DataFrame={
val sha1 = java.security.MessageDigest.getInstance("SHA-1")
val enCoder = new sun.misc.BASE64Encoder()
//enCoder.encode(sha1.digest(row.mkString.getBytes))
createDataFrame(df.map(row => {
        Row.fromSeq(row.toSeq ++ enCoder.encode(sha1.digest(row.mkString.getBytes)))
}), df.schema.add("hashing_id", StringType))

 }


def createDataFrame(rdd: RDD[Row], schema: StructType): DataFrame = {
sqlContext.createDataFrame(rdd, schema)
}

如何使用rdd实现sha1?

有人可以帮我这个

当我运行代码时,它会抛出异常

 17/09/12 13:45:20 ERROR yarn.ApplicationMaster: User class threw exception: org.apache.spark.SparkException: Task not serializable
 org.apache.spark.SparkException: Task not serializable

 Caused by: java.io.NotSerializableException: sun.misc.BASE64Encoder
 Serialization stack:
 - object not serializable (class: sun.misc.BASE64Encoder, value:   sun.misc.BASE64Encoder@46c0813)

1 个答案:

答案 0 :(得分:1)

你不能尝试这样的事情,它似乎在我的一些测试中起作用我只是运行:

 val newDF = sqlContext.createDataFrame(
rdd.map(x => Row(x.toSeq ++ Seq(x.toSeq.hashCode()): _*)), StructType(schema.iterator.toSeq ++ Seq(StructField("hashing_id", StringType, true))))

显然你需要将hashCode替换为你需要的哈希函数

编辑:使用sha1功能

在另一个类中定义你的函数

object Encoder {
  def sha1(s: Row): String = MessageDigest.getInstance("SHA-1").digest(s.mkString.getBytes()).toString
}

然后在原始课程中,您可以按如下方式调用您的函数

   val newDF = sqlContext.createDataFrame(wordsRDD.map(x => Row(x.toSeq ++ Seq(Encoder.sha1(x)): _*)), StructType(schema.iterator.toSeq ++ Seq(StructField("hashing_id", StringType, true)))).rdd.collect()