как создать и отсортировать по упорядоченной категориальной переменной в pyspark - PullRequest
2 голосов
/ 26 мая 2020

Я переношу код из pandas в pyspark. Мой исходный фрейм данных выглядит так:

   a         b  c
0  1    insert  1
1  2    update  1
2  3      seed  1
3  4    insert  2
4  5    update  2
5  6    delete  2
6  7  snapshot  1

, а операция (в python / pandas), которую я применяю:

df.b = pd.Categorical(df.b, ordered=True, categories=['insert', 'seed', 'update', 'snapshot', 'delete'])    
df.sort_values(['c', 'b'])

, приводит к выходному кадру данных :

   a         b  c
0  1    insert  1
2  3      seed  1
1  2    update  1
6  7  snapshot  1
3  4    insert  2
4  5    update  2
5  6    delete  2

Я не уверен, как лучше всего настроить упорядоченные категории с помощью pyspark, и мой первоначальный подход создает новый столбец с использованием case-when и пытается использовать его впоследствии:

df = df.withColumn(
    "_precedence",
    when(col("b") == "insert", 1)
    .when(col("b") == "seed", 2)
    .when(col("b") == "update", 3)
    .when(col("b") == "snapshot", 4)
    .when(col("b") == "delete", 5)
)

Ответы [ 2 ]

1 голос
/ 26 мая 2020

Вы также можете сделать это, используя coalesce с ur when statements.

from pyspark.sql import functions as F

categories=['insert', 'seed', 'update', 'snapshot', 'delete']

cols=[(F.when(F.col("b")==x,F.lit(y))) for x,y in zip(categories,[x for x in (range(1, len(categories)+1))])]

df.orderBy("c",F.coalesce(*cols)).show()

#+---+--------+---+
#|  a|       b|  c|
#+---+--------+---+
#|  1|  insert|  1|
#|  3|    seed|  1|
#|  2|  update|  1|
#|  7|snapshot|  1|
#|  4|  insert|  2|
#|  5|  update|  2|
#|  6|  delete|  2|
#+---+--------+---+
1 голос
/ 26 мая 2020

Вы можете использовать карту:

from pyspark.sql.functions import create_map, lit, col

categories=['insert', 'seed', 'update', 'snapshot', 'delete']

# per @HaleemurAli, adjusted the below list comprehension to create map
map1 = create_map([val for (i, c) in enumerate(categories) for val in (c, lit(i))])
#Column<b'map(insert, 0, seed, 1, update, 2, snapshot, 3, delete, 4)'>

df.orderBy('c', map1[col('b')]).show()
+---+---+--------+---+
| id|  a|       b|  c|
+---+---+--------+---+
|  0|  1|  insert|  1|
|  2|  3|    seed|  1|
|  1|  2|  update|  1|
|  6|  7|snapshot|  1|
|  3|  4|  insert|  2|
|  4|  5|  update|  2|
|  5|  6|  delete|  2|
+---+---+--------+---+

, чтобы изменить порядок в столбце-b: df.orderBy('c', map1[col('b')].desc()).show()

...