我的数据帧如下
cust_id req req_met
------- --- -------
1 r1 1
1 r2 0
1 r2 1
2 r1 1
3 r1 1
3 r2 1
4 r1 0
5 r1 1
5 r2 0
5 r1 1
我必须看客户,看看他们的要求有多少,看看他们是否至少满足了一次。可以有多个具有相同客户和需求的记录,其中一个具有MET,而不是满足。在上述情况下,我的输出应为
cust_id
-------
1
2
3
我所做的是
# say initial dataframe is df
df1 = df
.groupby('cust_id')
.countdistinct('req')
.alias('num_of_req')
.sum('req_met')
.alias('sum_req_met')
df2 = df1.filter(df1.num_of_req == df1.sum_req_met)
,但在少数情况下,它没有得到正确的结果
如何完成?
首先,我只是从上面给出的玩具数据集
from pyspark.sql.functions import col
import pyspark.sql.functions as fn
df = spark.createDataFrame([[1, 'r1', 1],
[1, 'r2', 0],
[1, 'r2', 1],
[2, 'r1', 1],
[3, 'r1', 1],
[3, 'r2', 1],
[4, 'r1', 0],
[5, 'r1', 1],
[5, 'r2', 0],
[5, 'r1', 1]], schema=['cust_id', 'req', 'req_met'])
df = df.withColumn('req_met', col("req_met").cast(IntegerType()))
df = df.withColumn('cust_id', col("cust_id").cast(IntegerType()))
我按cust_id
和req
组进行相同的操作,然后计算req_met
。之后,我将功能创建为将这些需求铺平到0,1
def floor_req(r):
if r >= 1:
return 1
else:
return 0
udf_floor_req = udf(floor_req, IntegerType())
gr = df.groupby(['cust_id', 'req'])
df_grouped = gr.agg(fn.sum(col('req_met')).alias('sum_req_met'))
df_grouped_floor = df_grouped.withColumn('sum_req_met', udf_floor_req('sum_req_met'))
现在,我们可以检查每个客户是否通过计算明显的要求和满足要求总数来满足所有要求。
df_req = df_grouped_floor.groupby('cust_id').agg(fn.sum('sum_req_met').alias('sum_req'),
fn.count('req').alias('n_req'))
最后,您只需要检查两个列是否相等:
df_req.filter(df_req['sum_req'] == df_req['n_req'])[['cust_id']].orderBy('cust_id').show()
select cust_id from
(select cust_id , MIN(sum_value) as m from
( select cust_id,req ,sum(req_met) as sum_value from <data_frame> group by cust_id,req )
temp group by cust_id )temp1
where m>0 ;
这将给出所需的结果
这是没有任何UDF的方法。有点棘手。基本上是由Cust_id组组,然后找到REQ_MET的总和。然后消除其sum == 0
的CUST_ID。
df.filter( ~df.cust_id.isin([x[0] for x in df.groupby('cust_id','req').agg(F.sum('req_met').alias('sum_req_met')).filter(col('sum_req_met')==0).select('cust_id').collect()]) ).select('cust_id').distinct().show()