Sparkでmd5ハッシュ列を数値列に変換する方法はありますか?
直接Decimalに変換してみました。また、convを使用してみました。しかし、隣人の仕事(以下を参照してください)。奇妙なことに、convは異なるハッシュを同じ値に変換します。
(1 to 5).toDF("id")
.withColumn("md5_id", md5($"id".cast("string")))
.withColumn("conv_id", conv($"md5_id", 16, 10))
.withColumn("num_id", $"md5_id".cast(DecimalType(38,0)))
.show(false)
+---+--------------------------------+--------------------+-------+
|id |md5_id |conv_id |num_id|
+---+--------------------------------+--------------------+-------+
|1 |c4ca4238a0b923820dcc509a6f75849b|18446744073709551615|null |
|2 |c81e728d9d4c2f636f067f89cc14862c|18446744073709551615|null |
|3 |eccbc87e4b5ce2fe28308fd9f2a7baf3|18446744073709551615|null |
|4 |a87ff679a2f3e71d9181a67b7542122c|18446744073709551615|null |
|5 |e4da3b7fbbce2345d7772b0674a318d5|18446744073709551615|null |
+---+--------------------------------+--------------------+-------+
更新
他の誰かが同じ問題にぶつかった場合、これは私のニーズに合っていました:
def toNum = udf((hex: String) =>
new java.math.BigInteger(hex.toUpperCase, 16)
)
(1 to 5).toDF("id")
.withColumn("hashed_id", toNum(substring(md5($"id".cast("string")), 0, 31)))
.show(false)
+---+--------------------------------------+
|id |hashed_id |
+---+--------------------------------------+
|1 |16348679641551244288068877217848318025|
|2 |16625230717330387431313232838613092450|
|3 |19672244359719724500030062827806555055|
|4 |13998420256418836516930895031794147618|
|5 |19012319408524223020738990858985681293|
+---+--------------------------------------+
root
|-- id: integer (nullable = false)
|-- hashed_id: decimal(38,0) (nullable = true)
さて、このケースは複雑で、その理由を説明します。MD5を数値に変換すると、通常はが作成されますBigInteger
。Sparkなしでそれを行う方法を示しましょう。
scala> val hex = "eccbc87e4b5ce2fe28308fd9f2a7baf3"
scala> new java.math.BigInteger(hex.toUpperCase, 16)
res28: java.math.BigInteger = 314755909755515592000481005244904880883
ご覧のとおり、数値は巨大で、実際には変換する10進数の38よりも大きく、この数値は39桁です。また、これはデフォルトのデータ型変換を使用するSparkではサポートされていません。したがって、これを解決する方法は、udfを使用してDecimal Libraryを使用することですが、データの精度がいくらか失われます。したがって、これを行う方法は次のとおりです。
def md5toIntString = udf((hex: String) =>
Decimal(new java.math.BigInteger(hex.toUpperCase, 16)).toString
)
(1 to 5).toDF("id")
.withColumn("md5_id", md5($"id".cast("string")))
.withColumn("conv_id", conv($"md5_id", 16, 10))
.withColumn("num_id", md5toIntString($"md5_id"))
.show(false)
そして、次のように結果を確認できます。
+---+--------------------------------+--------------------+---------------------------------------+
|id |md5_id |conv_id |num_id |
+---+--------------------------------+--------------------+---------------------------------------+
|1 |c4ca4238a0b923820dcc509a6f75849b|18446744073709551615|261578874264819908609102035485573088411|
|2 |c81e728d9d4c2f636f067f89cc14862c|18446744073709551615|266003691477286198901011725417809479212|
|3 |eccbc87e4b5ce2fe28308fd9f2a7baf3|18446744073709551615|314755909755515592000481005244904880883|
|4 |a87ff679a2f3e71d9181a67b7542122c|18446744073709551615|223974724102701384270894320508706361900|
|5 |e4da3b7fbbce2345d7772b0674a318d5|18446744073709551615|304197110536387568331823853743770900693|
+---+--------------------------------+--------------------+---------------------------------------+
そのため、この問題に直面しています。md5データのサイズ1 and len(2^128-1)
は約39桁です。
したがって、文字列として使用するか、別のタイプに変換することをお勧めします。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加