Python Pyspark基于对应列中匹配特定条件的最多多列创建列
假设我有一个Pyspark数据框,id为,3列表示代码桶Python Pyspark基于对应列中匹配特定条件的最多多列创建列,python,apache-spark,pyspark,Python,Apache Spark,Pyspark,假设我有一个Pyspark数据框,id为,3列表示代码桶 col_buckets ["code_1", "code_2", "code_3"] amt_buckets = ["code_1_amt", "code_2_amt", "code_3_amt" ] 和3列,表示对应代码段的金额 col_buckets ["code_1", "code_2", "code_3"] amt_buckets = ["code_1_amt", "code_2_amt", "code_3_amt" ]
col_buckets ["code_1", "code_2", "code_3"]
amt_buckets = ["code_1_amt", "code_2_amt", "code_3_amt" ]
和3列,表示对应代码段的金额
col_buckets ["code_1", "code_2", "code_3"]
amt_buckets = ["code_1_amt", "code_2_amt", "code_3_amt" ]
这是一个伪代码,我正在尝试做什么
for el in ['01', '06', '07']
df= df.withColumn("max_amt_{el}", max(df.select(max(**amt_buckets**) for corresponding col_indices of amt_buckets if ***any of col_buckets*** ==el)))
我将如何做到这一点
以下是一个数据帧示例:
我正在尝试为
spark2.4+
获取max_01、max_07和max_06列,您可以试试这个
df.show() #sample dataframe
#+----------+------+------+------+-----+-----+-----+
#|Primary_id|Code_1|Code_2|Code_3|Amt_1|Amt_2|Amt_3|
#+----------+------+------+------+-----+-----+-----+
#| Xxxxx998| null| 01| 04| 2000| 1000| 100|
#| Xxxxx997| 01| 01| 07| 200| 300| 400|
#| Xxxxx996| 07| null| null| 100| null| null|
#| Xxxx910| null| null| null| 300| 100| 200|
#+----------+------+------+------+-----+-----+-----+
from pyspark.sql import functions as F
dictionary = dict(zip(['Code_1','Code_2','Code_3'], ['Amt_1','Amt_2','Amt_3']))
df.withColumn("trial", F.array(*[F.array(F.col(x),F.col(y).cast("string"))\
for x,y in dictionary.items()]))\
.withColumn("Max_01",F.when(F.size(F.expr("""filter(trial,x-> exists(x,y->y='01'))"""))!=0,\
F.expr("""array_max(transform(filter(trial, x-> exists(x,y-> y='01')),z-> float(z[1])))"""))\
.otherwise(F.lit(0)))\
.withColumn("Max_06",F.when(F.size(F.expr("""filter(trial,x-> exists(x,y->y='06'))"""))!=0,\
F.expr("""array_max(transform(filter(trial, x-> exists(x,y-> y='06')),z-> float(z[1])))"""))\
.otherwise(F.lit(0)))\
.withColumn("Max_07",F.when(F.size(F.expr("""filter(trial,x-> exists(x,y->y='07'))"""))!=0,\
F.expr("""array_max(transform(filter(trial, x-> exists(x,y-> y='07')),z-> float(z[1])))"""))\
.otherwise(F.lit(0)))\
.drop("trial").show(truncate=False)
#+----------+------+------+------+-----+-----+-----+------+------+------+
#|Primary_id|Code_1|Code_2|Code_3|Amt_1|Amt_2|Amt_3|Max_01|Max_07|Max_06|
#+----------+------+------+------+-----+-----+-----+------+------+------+
#|Xxxxx998 |null |01 |04 |2000 |1000 |100 |1000 |0 |0 |
#|Xxxxx997 |01 |01 |07 |200 |300 |400 |300 |400 |0 |
#|Xxxxx996 |07 |null |null |100 |null |null |0 |100 |0 |
#|Xxxx910 |null |null |null |300 |100 |200 |0 |0 |0 |
#+----------+------+------+------+-----+-----+-----+------+------+------+
你从哪里得到01,06,07的列表,这是一个已经定义的标准变量吗?是的,这些是我们在dataframe中可能的代码列表中寻找的预定义代码好的,你也可以用dataframe的可视文本替换图像,以便可以复制它。谢谢。我更新了问题,将其包括在内it@MohammadMurtazaHashmi. 您好,谢谢您的帮助,是的,07列应该是100,而不是01Nice,我在想,如果可以使用另一个邮政编码和金额列的文字数组列的数组zip进行过滤,这是否可行。但现在无法测试:)@anky我也在考虑一种方法,使用结构使此动态化,这样我们就不必三次处理列(假设提供了要添加的列列表),只需在末尾选择
col.*
。b会不会更详细更干净。。等我回来再试试can@algorythmsofc,所以我们首先创建一列列表,其中第二维度是[Code_1,Amt_1]等等,然后我们使用高阶函数过滤器遍历列表,过滤掉任何与01(或7或6)不匹配的[[],然后我将其展平以得到[01200,01300],从中过滤出01以得到[200,300]然后用array_max取最大值。第二个过滤器可能不需要,但我不知道是否存在07或某个值可能大于该值的情况,所以我不想冒险。我知道了,这是字符串和array_max的一个小问题,我将在这里更新,并发布其他问题。检查我更新的解决方案,使用transform确保将字符串转换为数字