Dataframe 如何在PySpark中进行范围查找和搜索

Dataframe 如何在PySpark中进行范围查找和搜索,dataframe,pyspark,rdd,Dataframe,Pyspark,Rdd,我尝试在PySpark中编写一个函数,它可以在一定范围内进行组合搜索和查找值。以下是详细说明 我有两个数据集。 一个数据集,例如D1,基本上是一个查找表,如下所示: MinValue MaxValue Value1 Value2 --------------------------------- 1 1000 0.5 0.6 1001 2000 0.8 0.1 2001 4000 0.2 0.5 4

我尝试在PySpark中编写一个函数,它可以在一定范围内进行组合搜索和查找值。以下是详细说明

我有两个数据集。 一个数据集,例如
D1
,基本上是一个查找表,如下所示:

MinValue  MaxValue Value1 Value2
---------------------------------
1          1000      0.5     0.6
1001       2000      0.8     0.1
2001       4000      0.2     0.5
4001       9000      0.04    0.06
另一个数据集(如D2)是一个包含数百万条记录的表,例如:

ID      InterestsRate       Days       
----------------------------------
1       19.99               29
2       11.99               49
对于每个
ID
,我需要根据不同的信用额度计算最大回报,可能的值为
500、1000、2000、3000、5000

回报的计算方法如下,例如

f(x)=利率*天数*值1*值2

Value1
Value2
通过在
D1
中查找信用额度来确定。例如,如果信用额度为3000,则将返回查找的
D1
、0.2和0.5

对于
D2
中的每条记录,我想计算不同信用额度的回报率,并找出信用额度和回报率,从而获得最大回报率

到目前为止,我已经完成了两项功能:

我将查找函数定义为

def LookUp(value):
    filter_str = "MinValue <=" + str(value) + " and MaxValue >=" + str(value)
    return D1.filter(filter_str)
出乎意料的是,我遇到了错误,我在谷歌上搜索到我不能在RDD(
D2
)上的转换中使用数据帧(
D1

我还在谷歌上搜索到,可能的解决方案是播放
D1
。然而,我不知道如何使它工作

请您谈谈如何在PySpark中实现此功能


谢谢

当您使用
spark
时,您应该考虑
SQL
和表联接,而不是在列表上循环

所以我要做的第一件事就是把你的信用额度列表变成一个表格,我们称之为
D3

credit_limit=[5001000200030005000]
D3=spark.createDataFrame([[x]代表信用额度中的x],“信用额度”])
D3.show()
#+-----------+
#|信用额度|
#+-----------+
#|        500|
#|       1000|
#|       2000|
#|       3000|
#|       5000|
#+-----------+
现在,您可以将此表连接到
D1
D2
以计算每个信用额度的回报,然后使用
窗口
函数选择最大回报,对每个回报进行排序。作为您,如果有平局,我们将选择最高信用额度

导入pyspark.sql.f函数
从pyspark.sql导入窗口
w=Window.partitionBy(“ID”).orderBy(f.desc(“Return”)、f.desc(“CreditLimit”))
D2.别名(“D2”).交叉连接(D3.别名(“D3”))\
.交叉连接(D1.别名(“D1”))\
.式中(“D1.MinValue和D1.MaxValue之间的D3.CreditLimit”)\
.带列(“返回”,f.expr(“D2.利率*D2.天数*D1.价值1*D1.价值2”))\
.withColumn(“秩”,f.Rank()。在(w)上方)\
。其中(“排名=1”)\
.下降(“排名”)\
.show()
#+---+-------------+----+-----------+--------+--------+------+------+------------------+
#|ID |利率|天数|信用额度|最小值|最大值|值1 |值2 |返回|
#+---+-------------+----+-----------+--------+--------+------+------+------------------+
#|  1|        19.99|  29|       1000|       1|    1000|   0.5|   0.6|173.91299999999998|
#|  2|        11.99|  49|       1000|       1|    1000|   0.5|   0.6|           176.253|
#+---+-------------+----+-----------+--------+--------+------+------+------------------+

我们在这里做2个笛卡尔产品,因此这可能无法很好地扩展,但请尝试一下。

根据您的表,500和1000的信用额度将始终返回
D1
中的同一行。由于您的“退货”(
tmp
)不是信用额度的函数,因此这两种退货总是返回相同的值。我为您提供了一个潜在的解决方案,但是如果您为这个示例提供了所需的输出,这将非常有用。(您的
搜索
功能中也有一个bug-
x
未定义。)感谢您的推荐。返回值完全取决于最小值和最大值。如果我改变它们,信用额度500和1000可能会落入不同的桶中。我明白了吗?好的,但在这个例子中,它们落在同一个桶中——因此回报是相同的。在这种情况下,您会选择什么值?最高信用额度?是的。如果两个信用额度给我相同的回报,最高信用额度将被退回。谢谢你的回答。我是Pypark的新手。。。。所以我们必须先了解每一行。万分感谢!还有一个问题:在我的真实案例中,计算要复杂得多。我可以用函数替换f.expr(“D2.interestRated2.DaysD1.Value1*D1.Value2”)吗?您可以,但可能的话,您应该尝试将计算写成sql表达式,因为它会更快。如果这是不可能的,您需要一个
udf
再问一个问题:partitionby和groupby之间有什么区别?实际上是一样的。当您使用窗口函数时,我们将分组称为分区。
def Search(rate, day):
    credit_limit = [500, 1000, 2000, 3000, 5000]
    max=0;
    cl=-1;
    for i in range(1: len(credit_limit)):
       v1 = lookup(credit_limit[i]).select("value1")
       v2 = lookup(credit_limit[i]).select("value2")
       tmp = rate*day*value1*value2
       if max < tmp: 
          max=tmp 
          cl=credit_limit[i]

    return (cl, max)  
res = D2.mapValues(lambda row: Search(row[1], row[2]))