【问题标题】:PySpark : Merge dataframes where one value(from 1st dataframe) is between two others(from 2nd dataframe)PySpark:合并数据帧,其中一个值(来自第一个数据帧)在另外两个(来自第二个数据帧)之间
【发布时间】:2019-05-03 19:09:19
【问题描述】:

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

数据框 A 有一个日期(“日期”)、数字(“数字”)和一个 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,在这些日期之间,我们有两个对应的行(行 #3,4)来自数据帧 Am 通过计算总和来合并它们。

所以结果行将是

| 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      |

【问题讨论】:

    标签: pyspark pyspark-sql


    【解决方案1】:

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

    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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-10
      • 2021-04-26
      • 1970-01-01
      • 1970-01-01
      • 2018-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多