it-roy-ru.com

Spark добавить новый столбец в dataframe со значением из предыдущей строки

Мне интересно, как я могу добиться следующего в Spark (Pyspark)

Начальный кадр данных:

+--+---+
|id|num|
+--+---+
|4 |9.0|
+--+---+
|3 |7.0|
+--+---+
|2 |3.0|
+--+---+
|1 |5.0|
+--+---+

Результирующий кадр данных:

+--+---+-------+
|id|num|new_Col|
+--+---+-------+
|4 |9.0|  7.0  |
+--+---+-------+
|3 |7.0|  3.0  |
+--+---+-------+
|2 |3.0|  5.0  |
+--+---+-------+

Мне обычно удается «добавить» новые столбцы в фрейм данных, используя что-то вроде: df.withColumn("new_Col", df.num * 10)

Однако я понятия не имею, как мне добиться этого «сдвига строк» ​​для нового столбца, чтобы новый столбец имел значение поля из предыдущей строки (как показано в примере). Я также не смог найти в документации API ничего о том, как получить доступ к определенной строке в DF по индексу.

Любая помощь будет оценена.

26
Kito

Вы можете использовать оконную функцию lag следующим образом 

from pyspark.sql.functions import lag, col
from pyspark.sql.window import Window

df = sc.parallelize([(4, 9.0), (3, 7.0), (2, 3.0), (1, 5.0)]).toDF(["id", "num"])
w = Window().partitionBy().orderBy(col("id"))
df.select("*", lag("num").over(w).alias("new_col")).na.drop().show()

## +---+---+-------+
## | id|num|new_col|
## +---+---+-------|
## |  2|3.0|    5.0|
## |  3|7.0|    3.0|
## |  4|9.0|    7.0|
## +---+---+-------+

но есть несколько важных вопросов:

  1. если вам нужна глобальная операция (не разделенная некоторыми другими столбцами/столбцами), она крайне неэффективна.
  2. вам нужен естественный способ упорядочить ваши данные. 

В то время как второй вопрос почти никогда не является проблемой, первый может быть нарушителем соглашения. Если это так, вы должны просто преобразовать DataFrame в RDD и вычислить lag вручную. Смотрите, например:

Другие полезные ссылки:

30
zero323
   val df = sc.parallelize(Seq((4, 9.0), (3, 7.0), (2, 3.0), (1, 5.0))).toDF("id", "num")
df.show
+---+---+
| id|num|
+---+---+
|  4|9.0|
|  3|7.0|
|  2|3.0|
|  1|5.0|
+---+---+
df.withColumn("new_column", lag("num", 1, 0).over(w)).show
+---+---+----------+
| id|num|new_column|
+---+---+----------+
|  1|5.0|       0.0|
|  2|3.0|       5.0|
|  3|7.0|       3.0|
|  4|9.0|       7.0|
+---+---+----------+
0
mputha