Je voudrais effectuer une jointure à gauche entre deux dataframes, mais les colonnes ne correspondent pas de manière identique. La colonne de jointure dans le premier dataframe a un suffixe supplémentaire par rapport au second dataframe.

from pyspark import SparkContext
import pyspark.sql.functions as f

sc = SparkContext()

df1 = sc.parallelize([
    ['AB-101-1', 'el1', 1.5],
    ['ABC-1020-1', 'el2', 1.3],
    ['AC-1030-1', 'el3', 8.5]
]).toDF(('id1', 'el', 'v1'))

df2 = sc.parallelize([
    ['AB-101', 3],
    ['ABC-1020', 4]
]).toDF(('id2', 'v2'))

Le dataframe que je voudrais obtenir à la suite de la jointure gauche est:

df_join = sc.parallelize([
    ['AB-101-1', 'el1', 1.5, 'AB-101', 3],
    ['ABC-1020-1', 'el2', 1.3, 'ABC-1020', 4],
    ['AC-103-1', 'el3', 8.5, None, None]
]).toDF(('id1', 'el', 'v1', 'id2', 'v2'))

Je serais ravi d'utiliser pyspark.sql.substring pour prendre "tous sauf les 2 derniers caractères", ou d'utiliser quelque chose comme pyspark.sql.like, mais je n'arrive pas à comprendre comment faire fonctionner l'un ou l'autre correctement dans le joindre.

1
abeboparebop 7 août 2017 à 19:14

2 réponses

Cette solution utilise split pour déconstruire le id1 d'origine, puis concat pour reconstruire le id2 plus court.

df1 = (
    df1
    .withColumn('id1_els', f.split('id1','-'))
    .withColumn('id2', 
                f.concat(f.col('id1_els').getItem(0)
                         , f.lit('-')
                         , f.col('id1_els').getItem(1)))
)

df_join = df1.join(df2, 'id2', 'left').show()

Mais je préfère utiliser une solution avec substring ou contains, car cela dépend fortement de la forme spécifique de mon champ ID.

1
abeboparebop 7 août 2017 à 16:31

Dans votre cas spécifique, regexp_extract est probablement votre meilleure option, mais dans le cas général, vous pouvez utiliser:

df_join = df1.join(df2, df2.id2.contains(df1.id1), how='left')
1
Robin Ali 21 déc. 2019 à 19:42