Tengo una columna de marco de datos pyspark que tiene datos como a continuación.

event_list
PL:1547497782:1547497782~ST:1548593509:1547497782
PU:1547497782:1547497782~MU:1548611698:1547497782:1~MU:1548612195:1547497782:0~ST:1548627786:1547497782
PU:1547497782:1547497782~PU:1547497782:1547497782~ST:1548637508:1547497782
PL:1548631949:0
PL:1548619200:0~PU:1548623089:1548619435~PU:1548629541:1548625887~RE:1548629542:1548625887~PU:1548632702:1548629048~ST:1548635966:1548629048
PL:1548619583:1548619584~ST:1548619610:1548619609
PL:1548619850:0~ST:1548619850:0~PL:1548619850:0~ST:1548619850:0~PL:1548619850:1548619851~ST:1548619856:1548619855

Solo estoy interesado en tener los primeros 10 dígitos después de PL: y los primeros 10 dígitos después de ST: (si existe). Para PL split, utilicé

df.withColumn('PL', split(df['event_list'], '\:')[1]) 

Para ST: dado que los registros tienen una longitud diferente a la lógica no funciona, puedo usar esto

df.withColumn('ST', split(df['event_list'], '\ST:')[1]) 

Que devuelve ST:1548619856:1548619855 y divide la primera parte nuevamente. Tengo 1.5 M de registros, así que me preguntaba si hay una mejor manera.

Aquí se espera la salida

PL              ST
154749778   1548593509
    null    1548627786
    null    1548637508
154863194   null
154861920   1548635966
154861958   1548619610
154861985   1548619856 
1
DanielG 26 may. 2020 a las 17:32

3 respuestas

La mejor respuesta

Una forma es usar la función integrada SparkSQL str_to_map :

df.selectExpr("str_to_map(event_list, '~', ':') as map1") \
  .selectExpr(
    "split(map1['PL'],':')[0] as PL", 
    "split(map1['ST'],':')[0] as ST"
).show()
+----------+----------+
|        PL|        ST|
+----------+----------+
|1547497782|1548593509|
|      null|1548627786|
|      null|1548637508|
|1548631949|      null|
|1548619200|1548635966|
|1548619583|1548619610|
|1548619850|1548619850|
+----------+----------+

Nota: puede reemplazar la función split anterior por la función substr (es decir, substr(map1['PL'],1,10)) en caso de que necesite exactamente los primeros 10 caracteres .

3
jxc 26 may. 2020 a las 15:04

Intente con una combinación de substring_index y subcadena

df.select(
 substring(
   substring_index(df['event_list'], 'PL:', -1), # Get the string starting from 'PL:'
  3, 10).as('PL')) # Skip the first 3 letters and take 10 chars
2
Alfilercio 26 may. 2020 a las 15:06

Otra forma es usar regexp_extract, algo así como

val result = df.withColumn("PL", regexp_extract(col("event_list"),"PL\\:(.{0,10})\\:",1))
               .withColumn("ST", regexp_extract(col("event_list"),"ST\\:(.{0,10})\\:",1))
1
mazaneicha 26 may. 2020 a las 15:21