You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用PySpark按3、6、12个月间隔获取V1数据生成衍生列

PySpark实现月度数据的滞后取值需求

方案一:基于实际月份差的准确关联法

这种方法不受数据行顺序影响,通过日期计算匹配对应月份的数值,是更可靠的生产级实现方式:

from pyspark.sql import SparkSession
from pyspark.sql.functions import add_months, date_format, to_date, col

# 初始化SparkSession
spark = SparkSession.builder.appName("monthly_lag_calculation").getOrCreate()

# 模拟输入数据
data = [
    ("202307", 10),
    ("202306", 20),
    ("202305", 30),
    ("202304", 40),
    ("202303", 50),
    ("202302", 60),
    ("202301", 70)
]
df = spark.createDataFrame(data, ["month", "V1"])

# 转换月份为日期格式,并计算3/6个月前的月份(转为YYYYMM格式)
df_with_target_months = df.withColumn("month_date", to_date(col("month"), "yyyyMM")) \
                          .withColumn("month_3ago", date_format(add_months(col("month_date"), -3), "yyyyMM")) \
                          .withColumn("month_6ago", date_format(add_months(col("month_date"), -6), "yyyyMM"))

# 关联自身获取对应月份的V1值,作为V2和V3
result_df = df_with_target_months.join(df.withColumnRenamed("V1", "V2"), 
                                       df_with_target_months["month_3ago"] == df["month"], 
                                       how="left") \
                                 .join(df.withColumnRenamed("V1", "V3"), 
                                       df_with_target_months["month_6ago"] == df["month"], 
                                       how="left") \
                                 .select(df_with_target_months["month"], 
                                         df_with_target_months["V1"], 
                                         "V2", "V3")

# 查看202307的结果
result_df.filter(col("month") == "202307").show()

执行后,202307的V2为40(对应202304的V1),V3为70(对应202301的V1),完全符合实际月份差的逻辑。


方案二:基于数据行顺序的滞后取值(匹配示例输出)

如果你的需求是严格按照现有数据的降序行顺序,取当前行之后第3/6行的V1值(匹配你给出的示例结果),可以使用窗口函数结合降序排序:

from pyspark.sql import SparkSession
from pyspark.sql.window import Window
from pyspark.sql.functions import lead, col

# 初始化SparkSession
spark = SparkSession.builder.appName("monthly_lag_by_row").getOrCreate()

# 模拟输入数据
data = [
    ("202307", 10),
    ("202306", 20),
    ("202305", 30),
    ("202304", 40),
    ("202303", 50),
    ("202302", 60),
    ("202301", 70)
]
df = spark.createDataFrame(data, ["month", "V1"])

# 定义窗口:保持数据的降序排列顺序
window_spec = Window.orderBy(col("month").desc())

# 使用lead函数获取当前行之后的指定行数值(示例中202307的V2对应第3行,需偏移2位;V3对应第6行,需偏移5位)
result_df = df.withColumn("V2", lead(col("V1"), 2).over(window_spec)) \
              .withColumn("V3", lead(col("V1"), 5).over(window_spec))

# 查看202307的结果
result_df.filter(col("month") == "202307").show()

执行后,202307的V2为30、V3为60,和你给出的示例输出完全一致。注意这种方法依赖固定的行顺序,若数据排序发生变化,结果会出错,仅适用于行顺序固定的场景。

内容的提问来源于stack exchange,提问作者Ian_Yu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 18:59:54