簡體   English   中英

加入兩個大表並獲取最新值

[英]Join two big tables and to get most recent value

我想加入兩個具有數百萬行的 Spark 數據框。 假設“id”是兩個數據框的公共列。 兩者也都有“日期”列。 但是,兩個表中的日期可能不匹配。 如果第一個表中的記錄在第二個表中沒有匹配的日期,則對於第二個表中的“值”列,應采用最近的觀察。 因此,我無法加入“id”和“date”。 我在下面創建了一個示例數據框。 鑒於數據量很大,執行此操作的最佳方法是什么?

import pandas as pd
a = pd.DataFrame({'id':[1,2,3,1,2,3,1,2,3, 1,2,3], 'date': ['2020-01-01', '2020-01-01', '2020-01-01', '2020-01-08', '2020-01-08', '2020-01-08', '2020-01-21', '2020-01-21', '2020-01-21', '2020-01-31', '2020-01-31', '2020-01-31']})

a = spark.createDataFrame(a)

b = pd.DataFrame({'id':[1,2,3,1,2,1,3,1,2], 'date': ['2019-12-25', '2019-12-25', '2019-12-25', '2020-01-08', '2020-01-08',  '2020-01-21', '2020-01-21', '2020-01-31', '2020-01-31'], 'value': [0.1,0.2,0.3,1,2,10,30,0.1,0.2]})

b = spark.createDataFrame(b)

required_result = pd.DataFrame({'id':[1,2,3,1,2,3,1,2,3, 1,2,3], 'date': ['2020-01-01', '2020-01-01', '2020-01-01', '2020-01-08', '2020-01-08', '2020-01-08', '2020-01-21', '2020-01-21', '2020-01-21', '2020-01-31', '2020-01-31', '2020-01-31'],
                               'value': [0.1,0.2,0.3, 1,2,0.3,10, 2,30,0.1,0.2, 30]})

您可以加入id並保留第二個 dataframe 的日期,該日期等於或低於第一個數據幀的日期。

data1_sdf.join(data2_sdf.withColumnRenamed('date', 'date_b'), 
               [data1_sdf.id == data2_sdf.id, 
                data1_sdf.date >= func.col('date_b')], 
               'left'
               ). \
    drop(data2_sdf.id). \
    withColumn('dates_diff', func.datediff('date_b', 'date')). \
    withColumn('max_dtdiff', 
               func.max('dates_diff').over(wd.partitionBy('id', 'date'))
               ). \
    filter(func.col('max_dtdiff') == func.col('dates_diff')). \
    drop('dates_diff', 'max_dtdiff'). \
    orderBy('id', 'date'). \
    show()

# +---+----------+----------+-----+
# | id|      date|    date_b|value|
# +---+----------+----------+-----+
# |  1|2020-01-01|2019-12-25|  0.1|
# |  1|2020-01-08|2020-01-08|  1.0|
# |  1|2020-01-21|2020-01-21| 10.0|
# |  1|2020-01-31|2020-01-31|  0.1|
# |  2|2020-01-01|2019-12-25|  0.2|
# |  2|2020-01-08|2020-01-08|  2.0|
# |  2|2020-01-21|2020-01-08|  2.0|
# |  2|2020-01-31|2020-01-31|  0.2|
# |  3|2020-01-01|2019-12-25|  0.3|
# |  3|2020-01-08|2019-12-25|  0.3|
# |  3|2020-01-21|2020-01-21| 30.0|
# |  3|2020-01-31|2020-01-21| 30.0|
# +---+----------+----------+-----+

看來,您可以僅在id上加入,因為此密鑰看起來分布良好。 您可以聚合一點 df b ,加入兩個 dfs,然后過濾並提取具有最大日期的值。

from pyspark.sql import functions as F

b = b.groupBy('id').agg(F.collect_list(F.array('date', 'value')).alias('dv'))
df = a.join(b, 'id', 'left')
df = df.select(
    a['*'],
    F.array_max(F.filter('dv', lambda x: x[0] <= F.col('date')))[1].alias('value')
)

df.show()
# +---+----------+-----+
# | id|      date|value|
# +---+----------+-----+
# |  1|2020-01-01|  0.1|
# |  1|2020-01-08|  1.0|
# |  3|2020-01-01|  0.3|
# |  3|2020-01-08|  0.3|
# |  2|2020-01-01|  0.2|
# |  2|2020-01-08|  2.0|
# |  1|2020-01-21| 10.0|
# |  1|2020-01-31|  0.1|
# |  3|2020-01-21| 30.0|
# |  3|2020-01-31| 30.0|
# |  2|2020-01-21|  2.0|
# |  2|2020-01-31|  0.2|
# +---+----------+-----+

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM