Изменить выбранные строки в столбцы - PullRequest
1 голос
/ 07 октября 2019

У меня есть фрейм данных со следующей структурой

+------+-------------+--------+
|region|          key|     val|
+--------------------+--------+
|Sample|row1         |       6|
|Sample|row1_category|   Cat 1|
|Sample|row1_Unit    |      Kg|
|Sample|row2         |       4|
|Sample|row2_category|   Cat 2|
|Sample|row2_Unit    |     ltr|
+------+-------------+--------+

Я пытался добавить столбец и выдвигать значения из строк в столбцы, но столбец категории и единицы измерения

Я хочучтобы преобразовать его в структуру ниже

+------+-------------+--------+--------+--------+
|region|          key|     val|Category|   Unit |
+--------------------+--------+--------+--------+
|Sample|row1         |       6|   Cat 1|      Kg|
|Sample|row2         |       4|   Cat 2|     ltr|
+------+-------------+--------+--------+--------+

Это мне нужно сделать для нескольких ключей, у меня будет строка 2, строка 3 и т. д.

Ответы [ 2 ]

2 голосов
/ 07 октября 2019
scala> df.show
+------+-------------+----+
|region|          key| val|
+------+-------------+----+
|Sample|         row1|   6|
|Sample|row1_category|Cat1|
|Sample|    row1_Unit|  Kg|
|Sample|         row2|   4|
|Sample|row2_category|Cat2|
|Sample|    row2_Unit| ltr|
+------+-------------+----+


scala> val df1 = df.withColumn("_temp", split( $"key" , "_")).select(col("region"), $"_temp".getItem(0) as "key",$"_temp".getItem(1) as "colType",col("val"))


scala> df1.show(false)
+------+----+--------+----+
|region|key |colType |val |
+------+----+--------+----+
|Sample|row1|null    |6   |
|Sample|row1|category|Cat1|
|Sample|row1|Unit    |Kg  |
|Sample|row2|null    |4   |
|Sample|row2|category|Cat2|
|Sample|row2|Unit    |ltr |
+------+----+--------+----+


scala> val df2 = df1.withColumn("Category", when(col("colType") === "category", col("val"))).withColumn("Unit", when(col("colType") === "Unit", col("val"))).withColumn("val", when(col("colType").isNull, col("val")))


scala> df2.show(false)
+------+----+--------+----+--------+----+
|region|key |colType |val |Category|Unit|
+------+----+--------+----+--------+----+
|Sample|row1|null    |6   |null    |null|
|Sample|row1|category|null|Cat1    |null|
|Sample|row1|Unit    |null|null    |Kg  |
|Sample|row2|null    |4   |null    |null|
|Sample|row2|category|null|Cat2    |null|
|Sample|row2|Unit    |null|null    |ltr |
+------+----+--------+----+--------+----+


scala> val df3 = df2.groupBy("region", "key").agg(concat_ws("",collect_set(when($"val".isNotNull, $"val"))).as("val"),concat_ws("",collect_set(when($"Category".isNotNull, $"Category"))).as("Category"), concat_ws("",collect_set(when($"Unit".isNotNull, $"Unit"))).as("Unit"))


scala> df3.show()
+------+----+---+--------+----+
|region| key|val|Category|Unit|
+------+----+---+--------+----+
|Sample|row1|  6|    Cat1|  Kg|
|Sample|row2|  4|    Cat2| ltr|
+------+----+---+--------+----+
1 голос
/ 07 октября 2019

вы можете достичь этого, сгруппировав по ключу и, возможно, региону и агрегировав с collect_list, используя ragex ^[^_]+, вы получите все символы до _ символа.

ОБНОВЛЕНИЕ : Вы можете использовать (\\d{1,}) regex, чтобы найти все числа из строки (захват групп), например, если у вас есть row_123_456_unit и ваша функция выглядит как regexp_extract('val,"(\\d{1,})",0), вы получите 123, если вы измените последний параметр на 1, тогда вы получите 456. Надеюсь, это поможет. тестовое регулярное выражение

  df.printSchema()
  df.show()

  val regex1 = "^[^_]+"  // until '_' character
  val regex2 = "(\\d{1,})"  // capture group of numbers

  df.groupBy('region, regexp_extract('key, regex1, 0))
    .agg('region, collect_list('key).as("key"), collect_list('val).as("val"))
    .select('region,
    'key.getItem(0).as("key"),
    'val.getItem(0).as("val"),
    'val.getItem(1).as("Category"),
    'val.getItem(2).as("Unit")
  ).show()

вывод:

root
 |-- region: string (nullable = true)
 |-- key: string (nullable = true)
 |-- val: string (nullable = true)

+------+-------------+-----+
|region|          key|  val|
+------+-------------+-----+
|Sample|         row1|    6|
|Sample|row1_category|Cat 1|
|Sample|    row1_Unit|   Kg|
|Sample|         row2|    4|
|Sample|row2_category|Cat 2|
|Sample|    row2_Unit|  ltr|
+------+-------------+-----+

+------+----+---+--------+----+
|region| key|val|Category|Unit|
+------+----+---+--------+----+
|Sample|row1|  6|   Cat 1|  Kg|
|Sample|row2|  4|   Cat 2| ltr|
+------+----+---+--------+----+
...