Moja ramka DataFrame wygląda następująco:

StudentID          Marks
100                ["20", "25.5", "40.23", "50"]
200                ["30", "20", "25", "40"]
300                ["20", "25", "50", "35"]

Muszę wyodrębnić marks w tablicy i utworzyć nową ramkę DataFrame. Jednak nie jestem w stanie wyodrębnić poza drugą wartość w DF (nie wiem, jak wybrać wszystkie znaki za pomocą wyrażenia regularnego ([0-9]+)(?:\.[0-9]+){3}.

df1.select(regexp_extract('StudentID', '(\w+)(,)', 1).alias("C1"), 
             regexp_extract('Marks', '([0-9]+)(?:\.[0-9]+){3}', 0).alias("C2"))

Ostatecznie należy utworzyć nową ramkę DataFrame z poniższym formatem:

StudentID  C1    C2    C3     C4
100        20    25.5  40.23  50
200        30    20    25     40
300        20    25    50     35

Z góry dziękuję.

2
Bbee 6 marzec 2020, 13:56

2 odpowiedzi

Najlepsza odpowiedź

Możesz podzielić ciąg, a następnie użyć element_at, aby przeciągnąć podciągi do oddzielnych kolumn:

df1.withColumn("marks_array", split( regexp_replace(col("Marks"), "\\[|\\]|\"", ""), ",")  )
      .withColumn("C1", element_at(col("marks_array"), 1))
      .withColumn("C2", element_at(col("marks_array"), 2))
      .withColumn("C3", element_at(col("marks_array"), 3))
      .withColumn("C4", element_at(col("marks_array"), 4))
      .drop("marks_array", "Marks")
      .show(false)
+---------+---+-----+------+---+
|StudentID|C1 |C2   |C3    |C4 |
+---------+---+-----+------+---+
|100      |20 | 25.5| 40.23| 50|
|200      |30 | 20  | 25   | 40|
|300      |20 | 25  | 50   | 35|
+---------+---+-----+------+---+
1
ernest_k 6 marzec 2020, 12:51

Możesz użyć from_json, aby przekonwertować kolumnę łańcuchową Marks na tablicę ciągów. Następnie pobierz elementy tablicy, aby utworzyć każdą kolumnę.

Jeśli jednak nie znasz rozmiaru tablic, możesz użyć transform, aby przekształcić ją w mapę, a następnie rozbić mapę i obrócić, aby uzyskać żądany wynik.

transform_expr = """transform(from_json(Marks, 'array<string>'), 
                              (x, i) -> struct(concat('C', i+1), x)
                             )
                 """

df.select(col("*"), explode(map_from_entries(expr(transform_expr)))) \
  .groupBy("StudentID").pivot("key").agg(first("value")) \
  .show()

#+---------+---+----+-----+---+
#|StudentID|C1 |C2  |C3   |C4 |
#+---------+---+----+-----+---+
#|100      |20 |25.5|40.23|50 |
#|200      |30 |20  |25   |40 |
#|300      |20 |25  |50   |35 |
#+---------+---+----+-----+---+

Uwaga: funkcje transfrom i map_from_entries są dostępne tylko dla Spark 2.4+

0
blackbishop 6 marzec 2020, 13:31