web-dev-qa-db-fra.com

pyspark générer un hachage de ligne de colonnes spécifiques et l'ajouter en tant que nouvelle colonne

Je travaille avec spark 2.2.0 et pyspark2.

J'ai créé un DataFrame df et j'essaye maintenant d'ajouter une nouvelle colonne "rowhash" Qui est le hachage sha2 de colonnes spécifiques dans le DataFrame.

Par exemple, disons que df a les colonnes: (column1, column2, ..., column10)

J'ai besoin de sha2((column2||column3||column4||...... column8), 256) dans une nouvelle colonne "rowhash".

Pour l'instant, j'ai essayé d'utiliser les méthodes ci-dessous:

1) Fonction hash() utilisée mais comme elle donne une sortie entière, elle n'est pas très utile

2) J'ai essayé d'utiliser la fonction sha2() mais elle échoue.

Disons que columnarray a un tableau de colonnes dont j'ai besoin.

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

puis

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

Cela échoue avec l'erreur "impossible à résoudre".

Merci ma gueule pour ta réponse. Comme je ne dois hacher que des colonnes spécifiques, j'ai créé une liste de ces noms de colonnes (dans hash_col) et changé votre fonction comme:

 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) 

Puis passé comme:

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

Il échoue cependant maintenant avec erreur:

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

Je peux voir la valeur de\ufffd dans l'une des colonnes, donc je ne sais pas s'il existe un moyen de gérer cela?

6
msashish

Si vous voulez avoir le hachage pour chaque valeur dans les différentes colonnes de votre jeu de données, vous pouvez appliquer une fonction conçue par vous-même via map au rdd de votre dataframe.

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)

Les résultats ressembleraient à:

+----+----+----+----+----------------------------------------------------------------+----------+
|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