как динамически разделять и группировать числа в pyspark

#python #pyspark #apache-spark-sql #pyspark-dataframes

#python #pyspark #apache-spark-sql #pyspark-фреймы данных

Вопрос:

у меня есть следующий столбец в фрейме данных, который содержит числа, состоящие из 6 цифр и кратные шести, чего я пытаюсь добиться, так это разбиения столбца на группы по 2 подгруппы по 3 цифры, поскольку существует взаимосвязь. Это фрейм данных,

  ------------------------ --- 
|Col1                    |len|
 ------------------------ --- 
|001200                  |6  |
|201400                  |6  |
|401800                  |6  |
|201400401800            |12 |
|001200201400401800      |18 |
|001200201400401800801999|24 |
 ------------------------ --- 
 

Чего я ожидаю, так это

  ------------------------ ------------------------------- --- 
|Col1                    |processed_column               |len|
 ------------------------ ------------------------------- --- 
|001200                  |001-200                        |6  |
|201400                  |201-400                        |6  |
|401800                  |401-800                        |6  |
|201400401800            |201-400,401-800                |12 |
|001200201400401800      |001-200,201-400,401-800        |18 |
|001200201400401800801999|001-200,201-400,401-800,801-999|24 |
 ------------------------ ------------------------------- --- 

 

Одно из решений, которое я могу придумать, — это проверить len и разделить его на основе этого, но тогда я должен продолжать писать условие F.when для каждой длины и разделять его соответствующим образом.

 df = df.withColumn(
            "processed_column",
            F.when(
                F.col("len") == 6,
                F.concat(
                    F.substring(F.col("Col1"), 0, 3),
                    F.lit("-"),
                    F.substring(F.col("Col1"), 3, 3),
                ),
            )
            .when(
                F.col("len") == 12,
                F.concat(
                    F.substring(F.col("Col1"), 0, 3),
                    F.lit("-"),
                    F.substring(F.col("Col1"), 4, 3),
                    F.lit(","),
                    F.substring(F.col("Col1"), 7, 3),
                    F.lit("-"),
                    F.substring(F.col("Col1"), 10, 3),
                ),
            )
            .otherwise(F.col("Col1")),
        )
 

есть ли лучший способ, который может обрабатывать это динамически?

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

1. используйте regexp_replace, а затем обрежьте лишнюю конечную запятую: df.withColumn('processed_column', F.expr(r"rtrim(',',regexp_replace(Col1, '(\d{3})(\d{3})', '$1-$2,'))"))

2. позвольте мне проверить это и дать вам обратную связь.

3. @jxc это работает, буду признателен, если вы сможете объяснить синтаксис регулярных выражений

Ответ №1:

Я не знаю pyspark, но string в Python, вы можете сделать это, чтобы изменить все строки, кратные шести, на стиль, который вы задали в вопросе.

 def f(s):
    return ','.join([s[i*6:i*6 3] '-' s[i*6 3:i*6 6] for i in range(len(s)//6)])
print(f('401800'))
print(f('201400401800'))
print(f('001200201400401800'))
print(f('001200201400401800801999'))
 

401-800
201-400,401-800
001-200,201-400,401-800
001-200,201-400,401-800,801-999

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

1. спасибо вам за это @watfe, я смог создать функцию udf, используя ее 🙂

Ответ №2:

 def myFunction(s):
    return ','.join([s[i*6:i*6 3] '-' s[i*6 3:i*6 6] for i in range(len(s)//6)])
udf_myFunction = F.udf(myFunction)
df.withColumn('new_string', udf_myFunction("Col1")).show()