在蜂巢中合并两列但结构不同的

时间:2019-06-12 23:32:16

标签: hive pyspark hiveql pyspark-sql

我已经加载了一个实木复合地板文件并创建了一个数据框,如下所示

----------------------------------------------------------------------
 time |  data1                | data2
-----------------------------------------------------------------------
1-40  | [ lion-> 34, bear -> 2 ] |  [ monkey -> [9,23], goose -> [4,5] ]

因此,data1列的数据类型为string->integer映射,而data2列的数据类型为string->array映射。

我想将上面的数据框分解为下面的结构

------------------------
time | key        | val
------------------------
1-40 | lion       | 34
1-40 | bear       | 2
1-40 | monkey_0   | 9
1-40 | monkey_1   | 23
1-40 | goose_0    | 4
1-40 | goose_1    | 5

我尝试通过在pyspark中使用udfs将data1和data2转换为与string->array相同的数据类型,然后按如下所示展开列

def to_map(col1, col2):
    for i in col1.keys():
        col2[i] = [col1[i]]
    return col2
caster= udf(to_map,MapType(StringType(),ArrayType(IntegerType())))
pm_df = pm_df.withColumn("animals", caster('data1', 'data2'))
pm_df.select('time',explode(col('animals')))

我还尝试通过假设配置单元sql比使用pysprak udfs具有更高的性能来使用配置单元sql。

rdd = spark.sparkContext.parallelize([[datetime.datetime.now(), {'lion': 34, 'bear': 2}, {'monkey': [9, 23], 'goose':[4,5]} ]])
df = rdd.toDF(fields)
df.createOrReplaceTempView("df")
df = spark.sql("select time, explode(data1), data2 from df")
df.createOrReplaceTempView("df")
df = spark.sql("select time,key as animal,value,posexplode(data2) from df").show(truncate=False)

但是我对下面的结果感到困惑,并且不知道如何按照我的要求合并拆分的列。上面的配置单元sql的输出是:

+--------------------------+------+-----+---+------+-------+
|time                      |animal|value|pos|key   |value  |
+--------------------------+------+-----+---+------+-------+
|2019-06-12 19:23:00.169739|bear  |2    |0  |goose |[4, 5] |
|2019-06-12 19:23:00.169739|bear  |2    |1  |monkey|[9, 23]|
|2019-06-12 19:23:00.169739|lion  |34   |0  |goose |[4, 5] |
|2019-06-12 19:23:00.169739|lion  |34   |1  |monkey|[9, 23]|
+--------------------------+------+-----+---+------+-------+

我知道在使用python udfs时,python处理器和JVM之间的通信会产生很多开销。有什么方法可以使用内置函数或Hive sql达到上述预期结果。

1 个答案:

答案 0 :(得分:2)

我将分别处理import os, sys dir_path = os.path.dirname(os.path.realpath(__file__)) # Open a file dirs = os.listdir(dir_path) i=1 # This would print all the files and directories for file in dirs: if file!='VBA.xlsm' and file!='VBA.py' and file!='~$VBA.xlsm': print(file) #print all the files i=str(i) #change to string for file name i=i + '.xls' #add extension os.rename(file,i) #rename the file size=len(i) i=i[0:size-4] #remove the extension i=int(i) #change back to numerical i=i+1 #new numerical name data1,然后 union 结果集:

data2