跨PySpark DataFrame列的字符串匹配

时间:2018-09-29 17:42:33

标签: python pyspark apache-spark-sql

在给定参考表的情况下,我试图标准化我的DataFrames的标题名称。

我的参考表是一个DataFrame,其行中有变量,标准名称和所有可能的变体名称都作为列:

+-------------+---------+---------+
|Standard_name|Variant_1|Variant_2|
+-------------+---------+---------+
|     Pressure|    Press|  Press_1|
|        Speed|   Speed_|     Rate|
+-------------+---------+---------+

说我有一个带有这些列名的数据的DataFrame:

['Pressure', 'Rate', 'Altitude']

我想在我的引用DataFrame中查找每个变量名称,如果存在则返回相应的Standard_name,或者如果表中尚未引用该变量,则保留原始变量。

因此,上述虚拟示例的预期结果应为:

[Pressure, 'Speed', Altitude]

这在常规Python Pandas中很容易做到,但是我不知道如何在Spark中做到这一点,在Spark中您不应该考虑行索引。

在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

尽管我同意上面的mayank agrawal的评论,但我还是尝试在Spark中解决此问题。

我改编了this solution以在大型词典中提取具有标准名称的每个变体的所有成对对应关系。然后,我将字典映射到标准头文件create a new column的数据集头文件上。

因此解决方案是:

from pyspark.sql import Row
from pyspark.sql.types import *
import pyspark.sql.functions as F
from itertools import chain


key_value_map = F.udf(lambda maps: {key:f[key] for f in maps for key in f},
    MapType(StringType(),StringType()))


map_df = variable_df
    .agg(F.collect_list(F.create_map(list(chain.from_iterable([[key, 'Standard'] for key in var_df.columns[2:]])))).alias('maps')) 
    .agg(F.collect_list(key_value_map('maps')))

result_dict = map_df.collect()  
ref_dict = result_dict[0][0][0]

corresp_df = header_df
    .withColumn('new_header', F.create_map([F.lit(x) for x in chain(*ref_dict.items())]).getItem(F.col('old_header')))    
    .withColumn("new_header", F.coalesce(F.col('new_header'), F.col('old_header')))

new_columns = corresp_df.select('new_header').rdd.flatMap(lambda row : row).collect()

renamed_df = data_df.toDF(*new_columns)

参考文献:

Dataframe pyspark to dict

pyspark create new column with mapping from a dict