@ ревностный ответ, кажется, делает свое дело.
Я могу предложить вам эквивалентный синтаксис pyspark
(поскольку pyspark
входит в число тегов)
Во-первых, создание вашего фрейма данных
import pyspark.sql.window as psw
import pyspark.sql.functions as psf
df = spark.createDataFrame([("a",None , 1), ("b", None ,1),
("c","b",2), ("d","c",3),
("e","b",2),("e","d",4)],
['name','dep','xyz'])
df.show(5)
+----+----+---+
|name| dep|xyz|
+----+----+---+
| a|null| 1|
| b|null| 1|
| c| b| 2|
| d| c| 3|
| e| b| 2|
+----+----+---+
only showing top 5 rows
Идея состоит в том, чтобы упорядочить по dep
: сначала значения Null
, а затем вы получите порядок букв. С psf.dense_rank
у вас нет пробелов в вашем заказе. Чтобы применить dense_rank
в Spark
, вам нужна функция Window
:
w = psw.Window.orderBy('dep')
df.withColumn("xyz", psf.dense_rank().over(w))
df.show(5)
+----+----+---+
|name| dep|xyz|
+----+----+---+
| a|null| 1|
| b|null| 1|
| c| b| 2|
| d| c| 3|
| e| b| 2|
+----+----+---+
only showing top 5 rows
Обновление
Для вашего второго вопроса я не видел ни одного шаблона, который бы позволял решение. Вам понадобится ряд psf.when
утверждений.
import pyspark.sql.functions as psf
df = spark.createDataFrame([('city', None),('state', None),
('country', 'city'),('country','state'),
('pin','country'),('pin','state'),
('continent','country'),('continent','pin'),
('continent','city')], ['name','type'])
df = df.withColumn("sequence", psf.when(
((psf.col('name') == "country" ) & (psf.col('type') == "city")) |
((psf.col('name') == "continent") & (psf.col('type') == "city")) |
((psf.col('name') == "pin") & (psf.col('type') == "state")) |
((psf.col('name') == "country") & (psf.col('type') == "state")),
2
).when(
((psf.col('name') == "pin") & (psf.col('type') == "country")) |
((psf.col('name') == "continent") & (psf.col('type') == "country"))
,
3
).when(
(psf.col('name') == "continent") & (psf.col('type') == "pin"),
4
).otherwise(1)
)
df.show(10)
+---------+-------+--------+
| name| type|sequence|
+---------+-------+--------+
| city| null| 1|
| state| null| 1|
| country| city| 2|
| country| state| 2|
| pin|country| 3|
| pin| state| 2|
|continent|country| 3|
|continent| pin| 4|
|continent| city| 2|
+---------+-------+--------+
Чтобы избежать psf.when
Поскольку в ваших условиях нет явной закономерности, я не вижу других способов сделать это. чем использовать цепочку when
или join
, которую я сейчас предлагаю
Идея состоит в том, чтобы создать фрейм данных, задающий условие для ваших двух столбцов, а затем объединить его. Решение не проверено.
conditions = spark.createDataFrame([('country', 'city',2),('continent','city',2),
('pin','state',2),('country','state',2),
('pin','country',3),('continent','country',3),
('continent','pin', 4)],
['name','type','sequence'])
df = df.join(psf.broadcast(conditions),
['name', 'type'], 'left_outer')
.fillna(1, subset=['sequence'])
Кстати, я использую psf.broadcast
для ускорения слияния, потому что conditions
DataFrame
должен быть разумного размера.
Если у вас есть Большое количество условий, я думаю, такой подход должен быть предпочтительным. Это сделает ваш код более читабельным