Python 3.x 按大小写使用列映射填充pyspark数据帧中另一列的值

Python 3.x 按大小写使用列映射填充pyspark数据帧中另一列的值,python-3.x,pyspark,pyspark-sql,pyspark-dataframes,Python 3.x,Pyspark,Pyspark Sql,Pyspark Dataframes,我有一个包含多列的数据框: +-----------+-----------+-----------+ | col1| col2| col3| +-----------+-----------+-----------+ | s1| c1| p3| | s2| c1| p3| | s1| c3| p3| |

我有一个包含多列的数据框:

+-----------+-----------+-----------+
|       col1|       col2|       col3|
+-----------+-----------+-----------+
|         s1|         c1|         p3|
|         s2|         c1|         p3|
|         s1|         c3|         p3|
|         s3|         c4|         p4|
|         s4|         c5|         p4|
|         s2|         c6|         p4|
+-----------+-----------+-----------+

现在我想实现的是,我想使用dict从多个列的映射中创建一个新的列(因为唯一值的数量很大,所以单个或case语句会很乏味)。 其思想是首先映射col1的值,然后如果新列中还有剩余的空值,则从col2映射,如果有更多的空值,则再次从col3映射,最后将剩余的空值替换为str文本:

col1_map = {'s1' : 'apple', 's3' : 'orange'}
col2_map = {'c1' : 'potato', 'c6' : 'tomato'}
col3_map = {'p3' : 'ball', 'p4' : 'bat'}

最终输出如下所示:

+-----------+-----------+-----------+-----------+
|       col1|       col2|       col3|       col4|
+-----------+-----------+-----------+-----------+
|         s1|         c1|         p3|      apple|
|         s2|         c1|         p3|     potato|
|         s1|         c3|         p3|      apple|
|         s3|         c4|         p4|     orange|
|         s4|         c5|         p4|        bat|
|         s2|         c6|         p4|     tomato|
+-----------+-----------+-----------+-----------+
到目前为止,我的方法是创建一个新专栏。然后去

from itertools import chain
from pyspark.sql.functions import create_map, lit

mapping_expr = create_map([lit(x) for x in chain(*col1_dict.items())])

df = df.withColumn('col4', mapping_expr[df['col4']])
这将从col1的映射中获取col4中的值。然而,我的问题是,如果我对col2重复此操作,并且col4中已经有来自col1的映射值,那么新的映射将替换它。我不想那样。
是否有人建议在新列中保持此值添加顺序?

您做得几乎正确,只是需要在后续操作中使用
mapping\u expr

from pyspark.sql.functions import col, create_map, lit, when
from itertools import chain
values = [('s1','c1','p3'),('s2','c1','p3'),('s1','c3','p3'),('s3','c4','p4'),('s4','c5','p4'),('s2','c6','p4')]
df = sqlContext.createDataFrame(values,['col1','col2','col3'])
df.show()
+----+----+----+
|col1|col2|col3|
+----+----+----+
|  s1|  c1|  p3|
|  s2|  c1|  p3|
|  s1|  c3|  p3|
|  s3|  c4|  p4|
|  s4|  c5|  p4|
|  s2|  c6|  p4|
+----+----+----+
字典,由您提供并创建它的映射

col1_map = {'s1' : 'apple', 's3' : 'orange'}
col2_map = {'c1' : 'potato', 'c6' : 'tomato'}
col3_map = {'p3' : 'ball', 'p4' : 'bat'}

#Applying the mapping of dictionary.
mapping_expr1 = create_map([lit(x) for x in chain(*col1_map.items())])
mapping_expr2 = create_map([lit(x) for x in chain(*col2_map.items())])
mapping_expr3 = create_map([lit(x) for x in chain(*col3_map.items())])
最后陆续申请。除此之外,我所做的就是检查在对
col1/col2
进行操作之后,是否仍然有空值,可以使用函数进行检查

df=df.withColumn('col4', mapping_expr1.getItem(col('col1')))
df=df.withColumn('col4', when(col('col4').isNull(),mapping_expr2.getItem(col('col2'))).otherwise(col('col4')))
df=df.withColumn('col4', when(col('col4').isNull(),mapping_expr3.getItem(col('col3'))).otherwise(col('col4')))
df.show()
+----+----+----+------+
|col1|col2|col3|  col4|
+----+----+----+------+
|  s1|  c1|  p3| apple|
|  s2|  c1|  p3|potato|
|  s1|  c3|  p3| apple|
|  s3|  c4|  p4|orange|
|  s4|  c5|  p4|   bat|
|  s2|  c6|  p4|tomato|
+----+----+----+------+

我觉得不错。不知怎的,它没有点击我如何使用isNull在这里。谢谢你的帮助。我会检查解决方案是否有任何错误,如果有,并将答案标记为接受。建议:为了可读性,更改
when(col('col4').isNull(),mapping_expr2.getItem(col('col2')))。否则(col('col4'))
合并(col('col4'),mapping_expr2.getItem(col('col2'))
)。同样的效果,只是更短+1.