在pyspark Dataframe上创建新的模式或列名称

时间:2017-08-31 15:33:13

标签: python apache-spark pyspark spark-dataframe

我看到this post除了我需要使用列表更改数据框的标题之外它有点帮助,因为它很长并且随着我输入的每个数据集而变化,所以我无法写出/新列名称中的硬编码。

例如:

df = sqlContext.read.load("./assets/"+filename, 
                          format='com.databricks.spark.csv', 
                          header='false', 
                          inferSchema='false')
devices = df.first()
metrics = df.take(2)[1]
# Adding the two header rows together as one as a way of later searching through and sorting rows
# delimiter is "..." since it doesn't occur anywhere in the data and we don't have to wory about multiple splits
header = [str(devices[i]) +"..."+ str(metrics[i]) for i in range(len(devices))]

df2 = df.toDF(header)

然后我当然得到这个错误:

  

IllegalArgumentException:u“要求失败:列数不匹配。\ nOld列名称(278):

标题长度= 278,列数相同。 所以,真正的问题是,当我有一个新名称列表时,如何对数据框中的标题进行非硬编码的重新命名?

我怀疑我必须不以实际列表对象的形式进行输入,但是如何在不迭代每个列的情况下执行此操作(使用selectexpr或别名并使用一个创建几个新的dfs(不可变))一次新的更新列?(哎)

2 个答案:

答案 0 :(得分:0)

您可以遍历旧列名称并将新列名称作为别名赋予它们。一个好方法是在python中使用函数zip

首先让我们创建列名列表:

old_cols = df.columns
new_cols = [str(d) + "..." + str(m) for d, m in zip(devices, metrics)]

虽然我假设“...”指的是另一个python对象,因为“...”在列名中不是一个好的字符序列。

最后:

df2 = df.select([df[oc].alias(nc) for oc, nc in zip(old_cols, new_cols)])

答案 1 :(得分:0)

我尝试了不同的方法。由于我想模拟硬编码列表(而不是实际列表对象),因此我使用了exec()语句以及使用所有链接头创建的字符串。

注意:这限制为255列。因此,如果你想要更多,你将不得不分手

for i in range(len(header)):
    # For the first of the column names, need to initiate the string header_str
    if i == 0:
        header_str = "'" + str(header[i])+"',"
    # For the last of the names, need a different string to close it without a comma
    elif i == len(header)-1:
        header_str = header_str + "'" + header[i] + "'"
    #For everything in the middle: just add it all together the same way
    else:
        header_str = header_str + "'" + header[i] + "',"

exec("df2 = df.toDF("+ header_str +")")