Dataframe 如何在PySpark中进行范围查找和搜索
我尝试在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
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]))