создайте диапазон между двумя буквенно-цифровыми значениями в pyspark

#python #pyspark

#питон #пыспарк

Вопрос:

У меня есть набор данных, в котором каждый элемент имеет строку «диапазон от» и «диапазон до» различных типов. Например, первый элемент может иметь 1A0 -gt; 1A9, а следующий элемент может быть 3C2 -gt;gt; 5F8 и так далее (с несколькими различными шаблонами, но обычно состоящий из статического раздела и раздела диапазона (кажется, что обычно любая буква статична, а цифры могут быть статичными или нет).

Есть ли в pyspark какая-либо готовая встроенная функция, которая может справиться с генерацией промежуточных значений в диапазоне? Или если нет никаких советов о том, как его построить?

вот мой случай :

 from pyspark.sql.types import *  spark = SparkSession.builder.master("local[*]")   .appName('SparkTest.com')   .getOrCreate()  data = [  ('A', ['100', '105']),  ('B', ['200']),  ('C', ['1A0','1A3']),   ('D', ['1BB', ]),   ('E', ['3C8', '3D2']) ] df = spark.createDataFrame(data, ["id", "label"], ArrayType(StringType())) df.show()   --- ----------  |id |label |  --- ----------  |A |[100, 105]| |B |[200] | |C |[1A0, 1A3]| |D |[1BB] | |E |[3C8, 3D2]|  --- ----------   

ожидаемый :

  --- -----  |id |label|  --- -----  |A |100 | |A |101 | |A |102 | |A |103 | |A |104 | |A |105 | |B |200 | |C |1A0 | |C |1A1 | |C |1A2 | |C |1A3 | |D |1BB | |E |3C8 | |E |3C9 | |E |3D0 | |E |3D1 | |E |3D2 |  --- -----   

Ответ №1:

Я бы использовал UDF, который возвращает массив полного диапазона значений, а затем использовал explode() бы этот массив. Вот моя попытка реализовать UDF.

 from pyspark.sql.functions import explode, udf  @udf(returnType=ArrayType(StringType())) def generate_range(endpoints):  if len(endpoints) == 1:  return endpoints  current, end = endpoints  results = [current]  # get values of each position and the modulo for the increment math  base = ["0" if "0" lt;= c lt;= "9" else "A" for c in current]  values = [ord(c) - ord(b) for c, b in zip(current, base)]  modulo = [10 if b == "0" else 26 for b in base]  while current lt; end:  # increment logic  idx = -1  values[idx]  = 1  while values[idx] == modulo[idx]:  values[idx] = 0  idx -= 1  values[idx]  = 1  current = "".join(chr(v   ord(b)) for v, b in zip(values, base))  results.append(current)  return results  df.select("id", explode(generate_range("label")).alias("label")).show()   --- -----  | id|label|  --- -----  | A| 100| | A| 101| | A| 102| | A| 103| | A| 104| | A| 105| | B| 200| | C| 1A0| | C| 1A1| | C| 1A2| | C| 1A3| | D| 1BB| | E| 3C8| | E| 3C9| | E| 3D0| | E| 3D1| | E| 3D2|  --- -----   

Примечание: Это предполагает, что длина элементов в диапазоне не будет увеличиваться в течение диапазона, и если это произойдет, произойдет сбой. Дайте мне знать, если это предположение неверно.