Jadi saya memiliki DataFrame PySpark yang diberikan, katakanlah df, terlihat seperti di bawah ini:

df.show()
+--------------------+-------------------+
|              series|          value    |
+--------------------+-------------------+
|     XXXX-AAAA      |          1        |
|     XXXX-BB        |          2        |
|     XXXX-CCCCC     |          3        |
+--------------------+-------------------+

Di kolom series, saya ingin menyingkirkan substring XXXX- (yaitu panjang 5 karakter), yang sama untuk setiap entri tunggal kolom itu, sehingga mendapatkan DataFrame berikut, katakan df2:

df2.show()
+--------------------+-------------------+
|              series|          value    |
+--------------------+-------------------+
|        AAAA        |          1        |
|        BB          |          2        |
|        CCCCC       |          3        |
+--------------------+-------------------+

Saya telah mencoba menggunakan metode substr tetapi, seperti yang dapat Anda bayangkan, tantangannya terletak pada variabilitas panjang setiap entri di kolom series. Kode yang saya coba adalah sebagai berikut:

from pyspark.sql.functions import length

df2 = df.withColumn('series_truncated', df.timestamp.substr(5, length(df.series)))
df2 = df2.drop('series')
df2 = df2.withColumnRenamed("series_truncated", "series")
df.show()

Bersama dengan kesalahan terkait:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-14-6585c018cd92> in <module>
      3 #print(length(df.series))
      4 #df_test.show()
----> 5 df = df.withColumn('series_truncated', df.timestamp.substr(15, length(df.series)))  # Eliminate the first 14 digits of the timestamp column
      6 
      7 #df_test = df.withColumn('length_series', length(df.series))

/usr/local/spark/python/pyspark/sql/column.py in substr(self, startPos, length)
    417                 .format(
    418                     startPos_t=type(startPos),
--> 419                     length_t=type(length),
    420                 ))
    421         if isinstance(startPos, int):

TypeError: startPos and length must be the same type. Got <class 'int'> and <class 'pyspark.sql.column.Column'>, respectively.

Adakah yang tahu bagaimana ini bisa diselesaikan?

Terima kasih banyak sebelumnya,

Marioanzas

0
Marioanzas 15 Januari 2021, 13:01

3 jawaban

Jawaban Terbaik

Dua arah:

import pyspark.sql.functions as F

df.withColumn('series', F.regexp_extract('series', 'XXXX-(.*)$', 1)).show()
+------+-----+
|series|value|
+------+-----+
|  AAAA|    1|
|    BB|    2|
| CCCCC|    3|
+------+-----+

Atau

import pyspark.sql.functions as F

df.withColumn('series', F.expr('substring(series, 6, length(series) - 5)')).show()
+------+-----+
|series|value|
+------+-----+
|  AAAA|    1|
|    BB|    2|
| CCCCC|    3|
+------+-----+

Perhatikan bahwa fungsi substring di Pyspark API tidak menerima objek kolom sebagai argumen, tetapi Spark SQL API menerimanya, jadi Anda perlu menggunakan F.expr dalam metode kedua.

1
mck 15 Januari 2021, 10:06
from pyspark.sql.functions import substring, length, col, expr
df.withColumn('series',expr('substring(series, 6, length(series))'))
1
Kishore 15 Januari 2021, 10:22

Anda juga dapat menggunakan fungsi right bersama dengan lenght untuk mendapatkan karakter length(series)-5 paling kanan dari string:

df.withColumn("series", expr("right(series, length(series)-5)")).show()

#+------+-----+
#|series|value|
#+------+-----+
#|  AAAA|    1|
#|    BB|    2|
#| CCCCC|    3|
#+------+-----+

Atau cukup replace XXXX- dengan string kosong '':

df.withColumn("series", expr("replace(series, 'XXXX-', '')")).show()

Namun perhatikan bahwa replace akan menghilangkan semua XXXX- kemunculan tidak hanya di awal string.

1
blackbishop 15 Januari 2021, 10:32