web-dev-qa-db-ja.com

pysparkは特定の列の行ハッシュを生成し、それを新しい列として追加します

私はspark 2.2.0およびpyspark2を使用しています。

DataFrame dfを作成して、DataFrameの特定の列のsha2ハッシュである新しい列_"rowhash"_を追加しようとしています。

たとえば、dfに次の列があるとします:_(column1, column2, ..., column10)_

新しい列_"rowhash"_にsha2((column2||column3||column4||...... column8), 256)が必要です。

とりあえず、以下の方法を試してみました:

1)hash()関数を使用しましたが、整数出力を提供するため、あまり役に立ちません

2)sha2()関数を使用してみましたが、失敗しました。

columnarrayに必要な列の配列があるとしましょう。

_def concat(columnarray):
    concat_str = ''
    for val in columnarray:
        concat_str = concat_str + '||' + str(val) 
    concat_str = concat_str[2:] 
    return concat_str 
_

その後

_df1 = df1.withColumn("row_sha2", sha2(concat(columnarray),256))
_

これは「解決できません」エラーで失敗します。

答えてくれてありがとう。特定の列のみをハッシュする必要があるので、それらの列名のリスト(hash_col)を作成し、関数を次のように変更しました。

_ def sha_concat(row, columnarray):
   row_dict = row.asDict()      #transform row to a dict
   concat_str = '' 
   for v in columnarray: 
       concat_str = concat_str + '||' + str(row_dict.get(v)) 
   concat_str = concat_str[2:] 
   #preserve concatenated value for testing (this can be removed later)
   row_dict["sha_values"] = concat_str  
   row_dict["sha_hash"] = hashlib.sha256(concat_str).hexdigest()
   return Row(**row_dict) 
_

次に、として渡されます:

_    df1.rdd.map(lambda row: sha_concat(row,hash_col)).toDF().show(truncate=False)
_

しかし、現在はエラーで失敗しています:

_    UnicodeEncodeError: 'ascii' codec can't encode character u'\ufffd' in position 8: ordinal not in range(128)
_

列の1つに\ ufffdの値が表示されるので、これを処理する方法があるかどうかわかりません。

6
msashish

データセットのさまざまな列の各値のハッシュが必要な場合は、mapを介して自己設計関数をデータフレームのrddに適用できます。

import hashlib
test_df = spark.createDataFrame([
    (1,"2",5,1),(3,"4",7,8),              
    ], ("col1","col2","col3","col4"))

def sha_concat(row):
    row_dict = row.asDict()                             #transform row to a dict
    columnarray = row_dict.keys()                       #get the column names
    concat_str = ''
    for v in row_dict.values():
        concat_str = concat_str + '||' + str(v)         #concatenate values
    concat_str = concat_str[2:] 
    row_dict["sha_values"] = concat_str                 #preserve concatenated value for testing (this can be removed later)
    row_dict["sha_hash"] = hashlib.sha256(concat_str).hexdigest() #calculate sha256
    return Row(**row_dict)

test_df.rdd.map(sha_concat).toDF().show(truncate=False)

結果は次のようになります。

+----+----+----+----+----------------------------------------------------------------+----------+
|col1|col2|col3|col4|sha_hash                                                        |sha_values|
+----+----+----+----+----------------------------------------------------------------+----------+
|1   |2   |5   |1   |1b0ae4beb8ce031cf585e9bb79df7d32c3b93c8c73c27d8f2c2ddc2de9c8edcd|1||2||5||1|
|3   |4   |7   |8   |cb8f8c5d9fd7165cf3c0f019e0fb10fa0e8f147960c715b7f6a60e149d3923a5|8||4||7||3|
+----+----+----+----+----------------------------------------------------------------+----------+
0
gaw