我需要幫助在這種情況下用新行填充缺失值:
這只是一個例子,但我有很多不同的行IDs。
輸入資料框:
| ID | 旗幟 | 日期 |
|---|---|---|
| 123 | 1 | 01/01/2021 |
| 123 | 0 | 01/02/2021 |
| 123 | 1 | 01/03/2021 |
| 123 | 0 | 01/06/2021 |
| 123 | 0 | 01/08/2021 |
| 777 | 0 | 01/01/2021 |
| 777 | 1 | 01/03/2021 |
所以我有一個有限的集合,dates我想直到最后一個ID(在示例中,對于ID = 123:01/01/2021、01/02/2021、01/03/2021...直到 01/08/2021 )。所以基本上我可以用日歷進行交叉連接,但我不知道如何在交叉連接后用規則或過濾器填充缺失值。
預期輸出:(以粗體顯示生成的缺失值)
| ID | 旗幟 | 日期 |
|---|---|---|
| 123 | 1 | 01/01/2021 |
| 123 | 0 | 01/02/2021 |
| 123 | 1 | 01/03/2021 |
| 123 | 1 | 01/04/2021 |
| 123 | 1 | 01/05/2021 |
| 123 | 0 | 01/06/2021 |
| 123 | 0 | 01/07/2021 |
| 123 | 0 | 01/08/2021 |
| 777 | 0 | 01/01/2021 |
| 777 | 0 | 01/02/2021 |
| 777 | 1 | 01/03/2021 |
uj5u.com熱心網友回復:
您可以先分組id計算最大值和最小值,date然后使用sequence函式,生成從min_date到的所有日期max_date。最后,加入原始資料幀并用每組id. 這是一個完整的作業示例:
您的輸入資料框:
from pyspark.sql import Window
import pyspark.sql.functions as F
df = spark.createDataFrame([
(123, 1, "01/01/2021"), (123, 0, "01/02/2021"),
(123, 1, "01/03/2021"), (123, 0, "01/06/2021"),
(123, 0, "01/08/2021"), (777, 0, "01/01/2021"),
(777, 1, "01/03/2021")
], ["id", "flag", "date"])
Groupbyid并為每個生成所有可能的日期id:
all_dates_df = df.groupBy("id").agg(
F.date_trunc("mm", F.max(F.to_date("date", "dd/MM/yyyy"))).alias("max_date"),
F.date_trunc("mm", F.min(F.to_date("date", "dd/MM/yyyy"))).alias("min_date")
).select(
"id",
F.expr("sequence(min_date, max_date, interval 1 month)").alias("date")
).withColumn(
"date", F.explode("date")
).withColumn(
"date",
F.date_format("date", "dd/MM/yyyy")
)
現在,在劃分為的視窗上左連接df和使用last函式id以填充空值:
w = Window.partitionBy("id").orderBy("date")
result = all_dates_df.join(df, ["id", "date"], "left").select(
"id",
"date",
*[F.last(F.col(c), ignorenulls=True).over(w).alias(c)
for c in df.columns if c not in ("id", "date")
]
)
result.show()
# --- ---------- ----
#| id| date|flag|
# --- ---------- ----
#|123|01/01/2021| 1|
#|123|01/02/2021| 0|
#|123|01/03/2021| 1|
#|123|01/04/2021| 1|
#|123|01/05/2021| 1|
#|123|01/06/2021| 0|
#|123|01/07/2021| 0|
#|123|01/08/2021| 0|
#|777|01/01/2021| 0|
#|777|01/02/2021| 0|
#|777|01/03/2021| 1|
# --- ---------- ----
uj5u.com熱心網友回復:
您可以找到DATE當前行中的值和下一行中的值之間的日期范圍,然后用于sequence生成所有中間日期并分解此陣列以填充缺失日期的值。
from pyspark.sql import functions as F
from pyspark.sql import Window
data = [(123, 1, "01/01/2021",),
(123, 0, "01/02/2021",),
(123, 1, "01/03/2021",),
(123, 0, "01/06/2021",),
(123, 0, "01/08/2021",),
(777, 0, "01/01/2021",),
(777, 1, "01/03/2021",), ]
df = spark.createDataFrame(data, ("ID", "FLAG", "DATE",)).withColumn("DATE", F.to_date(F.col("DATE"), "dd/MM/yyyy"))
window_spec = Window.partitionBy("ID").orderBy("DATE")
next_date = F.coalesce(F.lead("DATE", 1).over(window_spec), F.col("DATE") F.expr("interval 1 month"))
end_date_range = next_date - F.expr("interval 1 month")
df.withColumn("Ranges", F.sequence(F.col("DATE"), end_date_range, F.expr("interval 1 month")))\
.withColumn("DATE", F.explode("Ranges"))\
.withColumn("DATE", F.date_format("date", "dd/MM/yyyy"))\
.drop("Ranges").show(truncate=False)
輸出
--- ---- ----------
|ID |FLAG|DATE |
--- ---- ----------
|123|1 |01/01/2021|
|123|0 |01/02/2021|
|123|1 |01/03/2021|
|123|1 |01/04/2021|
|123|1 |01/05/2021|
|123|0 |01/06/2021|
|123|0 |01/07/2021|
|123|0 |01/08/2021|
|777|0 |01/01/2021|
|777|0 |01/02/2021|
|777|1 |01/03/2021|
--- ---- ----------
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/392726.html
標籤:数据框 阿帕奇火花 火花 apache-spark-sql 交叉连接
上一篇:一個條目中更多值的累積總和
