PySpark:合并数据帧,其中一个值(来自第一个数据帧)介于两个其他值(来自第二个数据帧)之间

PySpark : Merge dataframes where one value(from 1st dataframe) is between two others(from 2nd dataframe)

我需要根据一个标识符和条件合并两个数据帧,其中一个数据帧中的日期介于另一个数据帧中的两个日期和另一列的 groupby(计算总和)

Dataframe A 有日期 ("date")、数字 ("number") 和 ID ("id"):

| id    | date          | number | 

| 101   |  2018-12-01   | 250  |
| 101   |  2018-12-02   | 150  | 
| 102   |  2018-11-25   | 1000 | 
| 102   |  2018-10-26   | 2000 | 
| 102   |  2018-09-25   | 5000 | 
| 103   |  2018-10-26   | 200  | 
| 103   |  2018-10-27   | 2000 | 

Dataframe B 有 Id("id")、fromdate("fromdate") 和 todate("todate"):

| id    |    fromdate   | todate     | 

| 101   |  2018-10-01   | 2018-11-01 |
| 101   |  2018-11-02   | 2018-12-30 | 
| 102   |  2018-09-01   | 2018-09-30 | 
| 102   |  2018-10-01   | 2018-12-31 | 
| 103   |  2018-10-01   | 2018-10-30 | 
| 104   |  2018-10-01   | 2018-10-30 | 

现在我需要在 id 和 date 上合并这两个数据框,然后相应地对所有数字求和。 例如: 考虑数据框 B 中的第四行,对于 id 102,在这些日期之间,我们有来自数据框 Am 的两个对应行(第 3,4 行)通过计算总和来合并它们。

因此结果行将是

| id    |    fromdate   | todate     | sum  |

| 102   |  2018-10-01   | 2018-12-31 | 3000 |

最终结果应该是: |编号 |从日期|至今 |总和 |

| 101   |  2018-10-01   | 2018-11-01 | 0      |
| 101   |  2018-11-02   | 2018-12-30 | 400    |
| 102   |  2018-09-01   | 2018-09-30 | 5000   |
| 102   |  2018-10-01   | 2018-12-31 | 3000   |
| 103   |  2018-10-01   | 2018-10-30 | 2200   |
| 104   |  2018-10-01   | 2018-10-30 | 0      |

这是您可以遵循的详细方法 -

from pyspark.sql.types import * 

################
##Define Schema
################
schema1 = StructType([StructField('id', IntegerType(), True),
                     StructField('date', StringType(), True),
                     StructField('number', IntegerType(), True)
                     ]
                    )


schema2 = StructType([StructField('id', IntegerType(), True),
                     StructField('fromdate', StringType(), True),
                     StructField('todate', StringType(), True)
                     ]
                    )
################
##Prepare Data
################

data1  = [
(101,'2018-12-01',250 ),
(101,'2018-12-02',150 ), 
(102,'2018-11-25',1000), 
(102,'2018-10-26',2000), 
(102,'2018-09-25',5000), 
(103,'2018-10-26',200 ), 
(103,'2018-10-27',2000)
]

data2 = [
(101,'2018-10-01','2018-11-01'),
(101,'2018-11-02','2018-12-30'), 
(102,'2018-09-01','2018-09-30'), 
(102,'2018-10-01','2018-12-31'), 
(103,'2018-10-01','2018-10-30'), 
(104,'2018-10-01','2018-10-30')
]

################
##Create dataframe and type cast to date
################

df1 = spark.createDataFrame(data1, schema1)

df2 = spark.createDataFrame(data2, schema2)

df1 = df1.select(df1.id,df1.date.cast("date"),df1.number)

df2 = df2.select(df2.id,df2.fromdate.cast("date"),df2.todate.cast("date"))

定义连接条件并连接数据帧

################
##Define Joining Condition
################

cond = [df1.id == df2.id, df1.date.between(df2.fromdate,df2.todate)]

################
##Join dataframes using joining condition "cond" and aggregation
################

from pyspark.sql.functions  import coalesce

df2.\
    join(df1, cond,'left').\
    select(df2.id,df1.number,df2.fromdate,df2.todate).\
    groupBy('id','fromdate','todate').\
    sum('number').fillna(0).\
    show()