我有一个像这样的数据框...
+----------+-----+
| date|price|
+----------+-----+
|2019-01-01| 25|
|2019-01-02| 22|
|2019-01-03| 20|
|2019-01-04| -5|
|2019-01-05| -1|
|2019-01-06| -2|
|2019-01-07| 5|
|2019-01-08| -11|
+----------+-----+
我想基于一种逻辑来创建新列,该逻辑需要回顾其他行-不仅仅是同一行的列值
我正在尝试一些UDF,但是它采用了列的相应行值。我不知道如何查看其他行...
例如: 我想创建一个新列“ newprice”-就像这样...
+----------+-----+----------+
| date|price|new price
+----------+-----+----------+
|2019-01-01| 25| 25
|2019-01-02| 22| 22
|2019-01-03| 20| 20
|2019-01-04| -5| 20
|2019-01-05| -1| 20
|2019-01-06| -2| 20
|2019-01-07| 5| 5
|2019-01-08| -11| 5
+----------+-----+-----------+
基本上,新列值中的每一行都不基于相应行的值,而是其他行的值...
逻辑:如果价格为负数,则回顾前几天,如果该日为正值-采取该价格或再返回一天直到有正值可用...
dateprice = [('2019-01-01',25),('2019-01-02',22),('2019-01-03',20),('2019-01-04', -5),\
('2019-01-05',-1),('2019-01-06',-2),('2019-01-07',5),('2019-01-08', -11)]
dataDF = sqlContext.createDataFrame(dateprice, ('date', 'price'))
我们将不胜感激任何帮助。
答案 0 :(得分:0)
首先用new price
列填充price
列,但用null
替换负值。然后,您可以使用Fill in null with previously known good value with pyspark上显示的技术来获取最后一个非空值,在这种情况下,它将是最后一个正值。
例如:
from pyspark.sql.functions import col, last, when
from pyspark.sql import Window
w = Window.orderBy("date").rowsBetween(Window.unboundedPreceding, Window.currentRow)
dataDF.withColumn("new_price", when(col("price") >= 0, col("price")))\
.withColumn(
"new_price",
last('new_price', True).over(w)
)\
.show()
#+----------+-----+---------+
#| date|price|new_price|
#+----------+-----+---------+
#|2019-01-01| 25| 25|
#|2019-01-02| 22| 22|
#|2019-01-03| 20| 20|
#|2019-01-04| -5| 20|
#|2019-01-05| -1| 20|
#|2019-01-06| -2| 20|
#|2019-01-07| 5| 5|
#|2019-01-08| -11| 5|
#+----------+-----+---------+
在这里,我利用了以下事实:如果条件不匹配且未指定null
,则when
默认会返回otherwise
。
答案 1 :(得分:0)
我使用Spark SQL尝试了这一方法。让我分两部分解释我的解决方案,
首先,当价格为负数时,我们可以获取价格为正数的最近日期,否则我们可以填充价格本身,如下所示,
function ValidatePermissions(e)
{
var businessGroupID = $('#BusinessGroup').val();
var requestedPermission = $('#RequestedPermission').val();
//validating each selected container id with the selected permission id
for (var i = 0; i < businessGroupID.length; i++)
{
if (businessGroupID[i] != 'null') {
$.ajax({
url: '@Url.Action("ValidatePermissions")',
method: 'GET',
cache: false,
data: { containerID: businessGroupID[i], appPermissionID: requestedPermission },
success: handleSuccess
});
}
}
}
输出:
spark.sql("""
select *,
case when price < 0 then
max(lag(case when price < 0 then null else date end) over(order by date))
over(order by date rows between unbounded preceding and current row)
else price end as price_or_date
from dataset
""").show()
第二,您可以使用+----------+-----+-------------+
| date|price|price_or_date|
+----------+-----+-------------+
|2019-01-01| 25| 25|
|2019-01-02| 22| 22|
|2019-01-03| 20| 20|
|2019-01-04| -5| 2019-01-03|
|2019-01-05| -1| 2019-01-03|
|2019-01-06| -2| 2019-01-03|
|2019-01-07| 5| 5|
|2019-01-08| -11| 2019-01-07|
+----------+-----+-------------+
和此派生列在同一数据集上执行left join
。因此,现在价格在date
列中的价格将显示为price_or_date
。最后,我们可以对它们执行简单的null
。
结合它们,我们可以实现下面显示的最终查询以生成所需的输出,
coalesce
输出:
spark.sql("""
select
a.date
, a.price
, coalesce(b.price, a.price) as new_price
from
(
select *,
case when price < 0 then
max(lag(case when price < 0 then null else date end) over(order by date))
over(order by date rows between unbounded preceding and current row)
else price end as price_or_date
from dataset
) a
left join dataset b
on a.price_or_date = b.date
order by a.date""").show()
希望这会有所帮助。