Colonne concatenate in Apache Spark DataFrame


Risposte:


175

Con raw SQL puoi usare CONCAT:

  • In Python

    df = sqlContext.createDataFrame([("foo", 1), ("bar", 2)], ("k", "v"))
    df.registerTempTable("df")
    sqlContext.sql("SELECT CONCAT(k, ' ',  v) FROM df")
  • In 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")

A partire da Spark 1.5.0 è possibile utilizzare la concatfunzione con l'API DataFrame:

  • In Python:

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

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

C'è anche una concat_wsfunzione che accetta un separatore di stringa come primo argomento.


46

Ecco come puoi creare nomi personalizzati

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()

dà,

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

crea una nuova colonna concatenando:

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

4
litcrea una colonna di_
muone

34

Un'opzione per concatenare le colonne di stringhe in Spark Scala sta usando concat.

È necessario verificare la presenza di valori nulli . Perché se una delle colonne è nulla, il risultato sarà nullo anche se una delle altre colonne ha informazioni.

Utilizzando concate 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"))))

Utilizzando concate select:

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

Con entrambi gli approcci avrai un NEW_COLUMN il cui valore è una concatenazione delle colonne: COL1 e COL2 dal tuo df originale.


1
Ho provato il tuo metodo in pyspark ma non ha funzionato, avvertendo "col should be Column".
Sansone

@Samson scusa, ho controllato solo l'API di Scala
Ignacio Alorre

3
@IgnacioAlorre Se stai usando al concat_wsposto di concat, puoi evitare di verificare la presenza di NULL.
Aswath K

18

Se vuoi farlo usando DF, puoi usare un udf per aggiungere una nuova colonna basata su colonne esistenti.

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()

12

Da Spark 2.3 ( SPARK-22771 ) Spark SQL supporta l'operatore di concatenazione ||.

Per esempio;

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

10

Ecco un altro modo per farlo per 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|
+------------+

7

Ecco un suggerimento per quando non conosci il numero o il nome delle colonne nel Dataframe.

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

4

concat (* cols)

v1.5 e successive

Concatena più colonne di input insieme in una singola colonna. La funzione funziona con stringhe, colonne di array binari e compatibili.

Per esempio: new_df = df.select(concat(df.a, df.b, df.c))


concat_ws (sep, * cols)

v1.5 e successive

Simile a concatma utilizza il separatore specificato.

Per esempio: new_df = df.select(concat_ws('-', df.col1, df.col2))


map_concat (* cols)

v2.4 e versioni successive

Usato per concatenare mappe, restituisce l'unione di tutte le mappe date.

Per esempio: new_df = df.select(map_concat("map1", "map2"))


Utilizzando l'operatore di concatenazione di stringhe ( ||):

v2.3 e versioni successive

Per esempio: df = spark.sql("select col_a || col_b || col_c as abc from table_x")

Riferimento: Spark sql doc


2

In Spark 2.3.0, puoi fare:

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

1

In Java puoi farlo per concatenare più colonne. Il codice di esempio serve a fornire uno scenario e come usarlo per una migliore comprensione.

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;
    }
}

Il codice sopra ha concatenato col1, col2, col3 separato da "_" per creare una colonna con il nome "concatenatedCol".


1

Abbiamo la sintassi java corrispondente al processo seguente

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

0

Un altro modo per farlo in pySpark usando 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

In effetti, ci sono alcune bellissime astrazioni incorporate per realizzare la tua concatenazione senza la necessità di implementare una funzione personalizzata. Dato che hai menzionato Spark SQL, suppongo che tu stia cercando di passarlo come comando dichiarativo tramite spark.sql (). In tal caso, puoi eseguire in modo diretto passando il comando SQL come: SELECT CONCAT(col1, '<delimiter>', col2, ...) AS concat_column_name FROM <table_name>;

Inoltre, da Spark 2.3.0, puoi utilizzare comandi in righe con: SELECT col1 || col2 AS concat_column_name FROM <table_name>;

In cui, è il tuo delimitatore preferito (può essere anche uno spazio vuoto) ed è la tabella temporanea o permanente da cui stai cercando di leggere.


0

Possiamo anche usare semplicemente SelectExpr. df1.selectExpr ("*", "upper (_2 || _3) come nuovo")

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.