добавьте столбец в фрейм данных, созданный с помощью разрезанных столбцов в Scala

#scala #dataframe #apache-spark

Вопрос:

У меня есть следующий df:

 KSCHL01     VTEXT01         KWERT01     KSCHL02     VTEXT02                 KWERT02     KSCHL03     VTEXT03         KWERT03     id
ZBTB        Tarif de base   4455.00     ZBFA        Brut facturé            4455.00     ZBN Brut    Négocié         3645.00     1
ZBT         Brut Tarif.     222.75      ZFIF        Remises fin d'ordre     0.00        ZMAJ        Majorations     0.00        2
 

Я хочу разрезать его столбцы и преобразовать их в строки, это желаемый результат:

 id  KSCHL   VTEXT                   KWERT
1   ZBTB    Tarif de base           4455.00
1   ZBFA    Brut facturé            4455.00
1   ZBN     Brut Négocié            3645.00
2   ZBT     Brut Tarif.             222.75
2   ZFIF    Remises fin d'ordre     0.00
2   ZMAJ    Majorations             0.00
 

Вот что я сделал:

 for( i <- 0 to df.columns.length-4 by 3){
  var temp=df.select(df.columns.slice(i, i 3).map(col(_)): _*)
  val columns = temp.columns
  val regex = """[0-9]"""
  val replacingColumns = columns.map(regex.r.replaceAllIn(_, "")) # delete all digits in column names
  val resultDF = replacingColumns.zip(columns).foldLeft(temp){(tempdf, name) => tempdf.withColumnRenamed(name._2, name._1)}
  res=res.union(resultDF) # Append df to final DF
}
 

Это работает нормально, но не включает столбец идентификатора для всех строк. Он возвращает желаемый вывод, но без столбца идентификатора.

Я попытался добавить это после объявления временного кадра данных:

 temp = temp.withColumn("id", df.id)
 

но у меня была эта ошибка:

 error: value id in class Dataset cannot be accessed in org.apache.spark.sql.DataFrame
 

Есть идеи, почему, пожалуйста ? И каково же решение.

Спасибо.

Ответ №1:

Собственное решение для искры

 df.withColumn("c1", map(lit("a"), 'vtext01, lit("b"), 'kwert01))
 .withColumn("c2", map(lit("a"), 'vtext02, lit("b"), 'kwert02))
 .withColumn("c3", map(lit("a"), 'vtext03, lit("b"), 'kwert03))
 .withColumn("flipped", explode(array('c1, 'c2, 'c3)))
 .withColumn("vtext", map_values('flipped)(0)) 
 .withColumn("kwert", map_values('flipped)(1)) 
 .drop("c1", "c2", "c3", "flipped")
 

Он создает карту значений ключей для каждой из комбинаций v и k, а затем взрывает их (таким образом, строки утрояются). Затем он принимает значения в этих картах, чтобы поместить их обратно в окончательные столбцы vtext и kwert.

Комментарии:

1. что делать, если количество столбцов является динамическим ?

2. Это все равно будет работать. Вам нужно будет предоставить более подробную информацию о том, что вы подразумеваете под динамикой. Будет ли количество столбцов ci просто каким-то числом 1…x? Будут ли выровнены vtexti, kwerti и ci, или будет что-то вроде c7, использующего vtext03 и kwert11? Если это первый, то все равно довольно просто.

Ответ №2:

Сначала вы создаете 3 кадра данных на основе этого кадра данных

 val df1 = df.select(col("KSCHL01").as("KSCHL"), col("VTEXT01").as("VTEXT"), col("KWERT01").as("KWERT"), col("id"))
 

Выход

 KSCHL       VTEXT           KWERT       id
ZBTB        Tarif de base   4455.00      1
ZBT         Brut Tarif.     222.75       2
 

Затем

 val df2 = df.select(col("KSCHL02").as("KSCHL"), col("VTEXT02").as("VTEXT"), col("KWERT02").as("KWERT"), col("id"))
 

Выход

 KSCHL       VTEXT                   KWERT       id
ZBFA        Brut facturé            4455.00     1
ZFIF        Remises fin d'ordre     0.00        2
 

Затем

 val df3 = df.select(col("KSCHL03").as("KSCHL"), col("VTEXT03").as("VTEXT"), col("KWERT03").as("KWERT"), col("id"))
 

Выход

  KSCHL       VTEXT          KWERT       id
 ZBN Brut    Négocié        3645.00     1
 ZMAJ        Majorations    0.00        2
 

Затем вы можете применить объединение к этим трем кадрам данных

 val finalDataframe = df1.union(df2).union(df3)
finalDataframe.show()
 

Выход

 id  KSCHL   VTEXT                   KWERT
1   ZBTB    Tarif de base           4455.00
1   ZBFA    Brut facturé            4455.00
1   ZBN     Brut Négocié            3645.00
2   ZBT     Brut Tarif.             222.75
2   ZFIF    Remises fin d'ordre     0.00
2   ZMAJ    Majorations             0.00
 

Комментарии:

1. что делать, если количество столбцов является динамическим ?