web-dev-qa-db-fra.com

Concaténer des colonnes dans Apache Spark DataFrame

Comment concaténer deux colonnes dans un Apache Spark DataFrame? Existe-t-il une fonction que Spark SQL peut utiliser?

69
Nipun

Avec le SQL brut, vous pouvez utiliser CONCAT:

  • En python

    df = sqlContext.createDataFrame([("foo", 1), ("bar", 2)], ("k", "v"))
    df.registerTempTable("df")
    sqlContext.sql("SELECT CONCAT(k, ' ',  v) FROM df")
    
  • En scala

    import sqlContext.implicits._
    
    val df = sc.parallelize(Seq(("foo", 1), ("bar", 2))).toDF("k", "v")
    df.registerTempTable("df")
    sqlContext.sql("SELECT CONCAT(k, ' ',  v) FROM df")
    

Depuis Spark 1.5.0, vous pouvez utiliser la fonction concat avec l’API DataFrame:

  • En Python:

    from pyspark.sql.functions import concat, col, lit
    
    df.select(concat(col("k"), lit(" "), col("v")))
    
  • En Scala:

    import org.Apache.spark.sql.functions.{concat, lit}
    
    df.select(concat($"k", lit(" "), $"v"))
    

Il existe également une fonction concat_ws qui prend un premier séparateur de chaîne.

123
zero323

Voici comment vous pouvez nommer personnalisé

import pyspark
from pyspark.sql import functions as sf
sc = pyspark.SparkContext()
sqlc = pyspark.SQLContext(sc)
df = sqlc.createDataFrame([('row11','row12'), ('row21','row22')], ['colname1', 'colname2'])
df.show()

donne, 

+--------+--------+
|colname1|colname2|
+--------+--------+
|   row11|   row12|
|   row21|   row22|
+--------+--------+

créer une nouvelle colonne en concaténant:

df = df.withColumn('joined_column', 
                    sf.concat(sf.col('colname1'),sf.lit('_'), sf.col('colname2')))
df.show()

+--------+--------+-------------+
|colname1|colname2|joined_column|
+--------+--------+-------------+
|   row11|   row12|  row11_row12|
|   row21|   row22|  row21_row22|
+--------+--------+-------------+
25
muon

Si vous souhaitez utiliser DF, vous pouvez utiliser un fichier UDF pour ajouter une nouvelle colonne en fonction des colonnes existantes.

val sqlContext = new SQLContext(sc)
case class MyDf(col1: String, col2: String)

//here is our dataframe
val df = sqlContext.createDataFrame(sc.parallelize(
    Array(MyDf("A", "B"), MyDf("C", "D"), MyDf("E", "F"))
))

//Define a udf to concatenate two passed in string values
val getConcatenated = udf( (first: String, second: String) => { first + " " + second } )

//use withColumn method to add a new column called newColName
df.withColumn("newColName", getConcatenated($"col1", $"col2")).select("newColName", "col1", "col2").show()
15
Danish Shrestha

Une option pour concaténer des colonnes de chaîne dans Spark Scala consiste à utiliser concat.

Il est nécessaire de vérifier les valeurs nulles . Car si l'une des colonnes est nulle, le résultat le sera même si l'une des autres colonnes contient des informations.

Utiliser concat et withColumn:

val newDf =
  df.withColumn(
    "NEW_COLUMN",
    concat(
      when(col("COL1").isNotNull, col("COL1")).otherwise(lit("null")),
      when(col("COL2").isNotNull, col("COL2")).otherwise(lit("null"))))

Utiliser concat et select:

val newDf = df.selectExpr("concat(nvl(COL1, ''), nvl(COL2, '')) as NEW_COLUMN")

Avec les deux approches, vous aurez un NEW_COLUMN dont la valeur est une concaténation des colonnes: COL1 et COL2 de votre df d'origine. 

9
Ignacio Alorre

Voici une autre façon de faire cela pour pyspark:

#import concat and lit functions from pyspark.sql.functions 
from pyspark.sql.functions import concat, lit

#Create your data frame
countryDF = sqlContext.createDataFrame([('Ethiopia',), ('Kenya',), ('Uganda',), ('Rwanda',)], ['East Africa'])

#Use select, concat, and lit functions to do the concatenation
personDF = countryDF.select(concat(countryDF['East Africa'], lit('n')).alias('East African'))

#Show the new data frame
personDF.show()

----------RESULT-------------------------

84
+------------+
|East African|
+------------+
|   Ethiopian|
|      Kenyan|
|     Ugandan|
|     Rwandan|
+------------+
6
Teddy Belay

Voici une suggestion à suivre lorsque vous ne connaissez pas le numéro ou le nom des colonnes du Dataframe.

val dfResults = dfSource.select(concat_ws(",",dfSource.columns.map(c => col(c)): _*))
4
wones0120

À partir de Spark 2.3 ( SPARK-22771 ) Spark SQL prend en charge l'opérateur de concaténation ||

Par exemple;

val df = spark.sql("select _c1 || _c2 as concat_column from <table_name>")
3
Krishas

Dans Spark 2.3.0, vous pouvez effectuer les tâches suivantes:

spark.sql( """ select '1' || column_a from table_a """)
1
Charlie 木匠

En Java, vous pouvez faire cela pour concaténer plusieurs colonnes. L'exemple de code consiste à vous fournir un scénario et à vous en servir pour une meilleure compréhension.

SparkSession spark = JavaSparkSessionSingleton.getInstance(rdd.context().getConf());
Dataset<Row> reducedInventory = spark.sql("select * from table_name")
                        .withColumn("concatenatedCol",
                                concat(col("col1"), lit("_"), col("col2"), lit("_"), col("col3")));


class JavaSparkSessionSingleton {
    private static transient SparkSession instance = null;

    public static SparkSession getInstance(SparkConf sparkConf) {
        if (instance == null) {
            instance = SparkSession.builder().config(sparkConf)
                    .getOrCreate();
        }
        return instance;
    }
}

Le code ci-dessus concaténé col1, col2, col3 séparé par "_" pour créer une colonne avec le nom "concatenatedCol".

0
wandermonk

En effet, il existe de belles abstractions intégrées pour vous permettre d'accomplir votre concaténation sans avoir à implémenter une fonction personnalisée. Puisque vous avez mentionné Spark SQL, je suppose que vous essayez de le transmettre en tant que commande déclarative via spark.sql (). Si tel est le cas, vous pouvez accomplir directement en passant une commande SQL telle que: SELECT CONCAT(col1, '<delimiter>', col2, ...) AS concat_column_name FROM <table_name>;

De plus, à partir de Spark 2.3.0, vous pouvez utiliser des commandes alignées avec: SELECT col1 || col2 AS concat_column_name FROM <table_name>;

Où est votre séparateur préféré (peut-être aussi un espace vide) et la table temporaire ou permanente que vous essayez de lire.

0
user11768920

Une autre façon de le faire dans pySpark en utilisant sqlContext ...

#Suppose we have a dataframe:
df = sqlContext.createDataFrame([('row1_1','row1_2')], ['colname1', 'colname2'])

# Now we can concatenate columns and assign the new column a name 
df = df.select(concat(df.colname1, df.colname2).alias('joined_colname'))
0
Gur