J'ai une trame de données comme ci-dessous
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
Je dois regarder les clients, voir combien d'exigences ils ont et voir s'ils ont satisfait au moins une fois. Il peut y avoir plusieurs enregistrements avec le même client et la même exigence, l'un avec satisfait et non satisfait. Dans le cas ci-dessus, ma sortie devrait être
cust_id
-------
1
2
3
Ce que j'ai fait c'est
# 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)
Mais dans certains cas, les résultats ne sont pas corrects
Comment cela peut-il être fait ?
Tout d'abord, je vais simplement préparer un ensemble de données de jouets à partir de ce qui précède,
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()))
Je fais la même chose par groupe par cust_id
et req
puis comptez le req_met
. Après cela, je crée une fonction pour fixer ces exigences à seulement 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'))
Maintenant, nous pouvons vérifier si chaque client a satisfait à toutes les exigences en comptant le nombre distinct d'exigences et le nombre total d'exigences satisfaites.
df_req = df_grouped_floor.groupby('cust_id').agg(fn.sum('sum_req_met').alias('sum_req'),
fn.count('req').alias('n_req'))
Enfin, il suffit de vérifier si deux colonnes sont égales:
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 ;
Cela donnera le résultat souhaité