Python 如何对上一个组(月)的同一行执行自联接,以在Pyspark中引入具有不同表达式的其他列

Python 如何对上一个组(月)的同一行执行自联接,以在Pyspark中引入具有不同表达式的其他列,python,dataframe,pyspark,hive,pyspark-dataframes,Python,Dataframe,Pyspark,Hive,Pyspark Dataframes,根据给出的公式计算以下从值1_1到值4_4的新列时出错 输入: Month_no|value1 |value2 |value3 |value4| 01 |10 |20 |30 |40 | 01 |20 |30 |40 |50 | 01 |30 |40 |50 |60 | 02 |40 |50 |60 |70 | 02 |50

根据给出的公式计算以下从值1_1到值4_4的新列时出错

输入:

Month_no|value1 |value2 |value3 |value4|
  01    |10     |20     |30     |40    |
  01    |20     |30     |40     |50    |
  01    |30     |40     |50     |60    |
  02    |40     |50     |60     |70    |
  02    |50     |60     |70     |80    |
  02    |60     |70     |80     |90    |
  03    |70     |80     |90     |100   |
  03    |80     |90     |100    |110   |
  03    |90     |100    |110    |120   |
值1_1和值2_2应基于exp:value1+prev进行计算。月份价值1。例如,对于第02个月,第一行的值1应为第01个月的第一行值1(10)+第02个月的第一行值1(40)=50

值3_3和值4_4的计算应基于exp:(值3+上个月的值3)/(qrt mnth no#)

qtr月号:每个季度内的月号

If Jan no# is 1
If Feb no# is 2
If Mar no# is 3
If Apr no# is 1
If May no# is 2
If Jun no# is 3
输出:值1_1和2_2按一个公式计算,值3_3和4_4按另一个公式计算

Month_no|value1 |value2 |value3 |value4 |value1_1|value2_2|value3_3   |value4_4   |
01      |10     |20     |30     |40     |10      |20      |30         |40         |
01      |20     |30     |40     |50     |20      |30      |40         |50         |
01      |30     |40     |50     |60     |30      |40      |50         |60         |
02      |40     |50     |60     |70     |50      |70      |45         |55         |
02      |50     |60     |70     |80     |70      |90      |55         |65         |
02      |60     |70     |80     |90     |90      |110     |65         |75         |
03      |70     |80     |90     |100    |120     |150     |45         |51.66666667|
03      |80     |90     |100    |110    |150     |180     |51.66666667|58.33333333|
03      |90     |100    |110    |120    |180     |210     |58.33333333|65         |

我试图通过加入和计算新的值,在每个月对当前和前一个月进行for循环。但对于数百万条记录来说,for循环会带来性能问题。是否有其他解决方法的建议???

您的问题不清楚。然而,基于数据,我将尝试回答这个问题

根据您的源数据,在每个月内,数据看起来像是按某种东西排序的。我将取值_1作为排序列。您可以根据自己的逻辑将其更改为其他内容。基于此排序列,我将生成行\号并在自联接中使用它

你可以尝试下面的方法来达到你的效果。以下代码在spark 2.x中给出了正确的结果。您可能需要调整它才能在spark环境中工作。请注意,您的公式和第3个月的结果集不匹配

from pyspark.sql import Window
from pyspark.sql.functions import row_number,lit,col,when

#storing your source data and forming it as a list of list
data=""" 01    |10     |20     |30     |40    
  01    |20     |30     |40     |50     
  01    |30     |40     |50     |60     
  02    |40     |50     |60     |70     
  02    |50     |60     |70     |80     
  02    |60     |70     |80     |90     
  03    |70     |80     |90     |100    
  03    |80     |90     |100    |110    
  03    |90     |100    |110    |120    """

data01=data.split('\n')
data02=[ item.split('|') for item in data01 ]

#creating variables with column names for convenience
month_no='Month_no';value1='value1';value2='value2';value3='value3';value4='value4';crownum="rownum";qtrMonthNo="qtrMonthNo";

#creating rdd & df based on your data
df=sc.parallelize(data02).toDF(['Month_no','value1','value2','value3','value4'])
sourcedata=df.selectExpr("cast(trim(month_no) as integer) as Month_no","cast(trim(value1) as integer) as value1","cast(trim(value2) as integer) as value2","cast(trim(value3) as integer) as value3","cast(trim(value4) as integer) as value4")

#Adding rownum to join with appropriate row in same month
rownum_window=Window.partitionBy(month_no).orderBy(value1)
df1=sourcedata.withColumn("rownum",row_number().over(rownum_window))

#preparing dataframes for join
df_left=df1 
df_right=df1.select(*[col(colm).alias("r_"+colm)  for colm in df1.columns ])

#joining dataframes
df_joined=df_left.join(df_right,( df_left.Month_no - 1 == df_right.r_Month_no )  & ( df_left.rownum==df_right.r_rownum )  ,"left").fillna(0)
df_joined=df_joined.withColumn(qtrMonthNo,when(df_joined.Month_no % 3 == 0, 3).otherwise(df_joined.Month_no % 3))
#not required
df_joined.cache()

#calculating value1_1 & value2_2
first_cal=df_joined.select((col("r_value1")+col("value1")).alias("value1_1"),(col("r_value2")+col("value2")).alias("value2_2"),qtrMonthNo,"r_value3","r_value4",*df1.columns)

#calculating value3_3 & value4_4
second_cal=first_cal.select(((col("r_value3")+col("value3")) / col("qtrMonthNo") ).alias("value3_3"),((col("r_value4")+col("value4")) / col("qtrMonthNo") ).alias("value4_4"),*first_cal.columns)

#final dataframe with necessary columns and sorted data
result_df=second_cal.orderBy(month_no,value1).drop(qtrMonthNo,crownum,"r_value3","r_value4")
result_df.show()

向我们展示您迄今为止尝试过的内容请说明错误和您迄今为止尝试过的代码。此外,您的内容与数据不匹配。第一行与下个月的第一行一起添加,未明确提及。请更正您的问题,使其更易于理解。已按要求在提供的链接中添加详细信息。感谢您的解释,您已经尝试了Windows方法。我不明白那一点。但是,您的添加是基于上个月的输入变量加上当前月份的值,而不是上个月新计算的列加上当前月份的输入值。我已在以下问题中详细说明了该问题: