代码之家  ›  专栏  ›  技术社区  ›  cph_sto

pyspark-在数据帧列中创建的列表类型为string而不是integer

  •  0
  • cph_sto  · 技术社区  · 7 年前

    我有一个数据框架-

    values = [('A',8),('B',7)]
    df = sqlContext.createDataFrame(values,['col1','col2'])
    df.show()
    +----+----+
    |col1|col2|
    +----+----+
    |   A|   8|
    |   B|   7|
    +----+----+
    

    我想要 list 属于 偶数 从0到 col2 .

    #Returns even numbers
    def make_list(col):
        return list(map(int,[x for x in range(col+1) if x % 2 == 0]))
    make_list = udf(make_list)
    
    df = df.withColumn('list',make_list(col('col2')))
    df.show()
    +----+----+---------------+
    |col1|col2|           list|
    +----+----+---------------+
    |   A|   8|[0, 2, 4, 6, 8]|
    |   B|   7|   [0, 2, 4, 6]|
    +----+----+---------------+
    df.printSchema()
    root
     |-- col1: string (nullable = true)
     |-- col2: long (nullable = true)
     |-- list: string (nullable = true)
    

    我得到了我想要的清单,但清单是 string 类型而不是 int ,正如您在 printschema 上面。

    我怎么才能拿到 列表 属于 int 类型?没有 int 类型,我不能 explode 这个数据文件。

    我怎么能得到一个 列表 属于 integers ?

    2 回复  |  直到 7 年前
        1
  •  2
  •   akuiper    7 年前

    您需要指定 udf 得到一个 list 属于 int 使用 ArrayType(IntegerType()) :

    from pyspark.sql.functions import udf, col
    from pyspark.sql.types import ArrayType, IntegerType
    
    # specify the return type as ArrayType(IntegerType())
    make_list_udf = udf(make_list, ArrayType(IntegerType()))
    
    df = df.withColumn('list',make_list_udf(col('col2')))
    df.show()
    +----+----+------------+                                                        
    |col1|col2|        list|
    +----+----+------------+
    |   A|   6|[0, 2, 4, 6]|
    |   B|   7|[0, 2, 4, 6]|
    +----+----+------------+
    
    df.printSchema()
    root
     |-- col1: string (nullable = true)
     |-- col2: long (nullable = true)
     |-- list: array (nullable = true)
     |    |-- element: integer (containsNull = true)
    

    或者如果你使用Spark 2.4,你可以使用新的 sequence 功能:

    values = [('A',8),('B',7)]
    df = sqlContext.createDataFrame(values,['col1','col2'])
    
    from pyspark.sql.functions import sequence, lit, col
    df.withColumn('list', sequence(lit(0), col('col2'), step=lit(2))).show()
    +----+----+---------------+
    |col1|col2|           list|
    +----+----+---------------+
    |   A|   8|[0, 2, 4, 6, 8]|
    |   B|   7|   [0, 2, 4, 6]|
    +----+----+---------------+
    
        2
  •  2
  •   pault Tanjin    7 年前

    事实证明, closed form function 它将获得通过将数字加入所需数字来表示的数字。 list 列。

    我们可以实现这个函数,然后使用一些字符串操作和正则表达式,只使用API函数就可以得到所需的输出。尽管这更复杂,但 应该 仍然比使用 udf .

    import pyspark.sql.functions as f
    
    def getEvenNumList(x):
        n = f.floor(x/2)
        return f.split(
            f.concat(
                f.lit("0,"), 
                f.regexp_replace(
                    (2./81.*(-9*n+f.pow(10, (n+1))-10)).cast('int').cast('string'), 
                    r"(?<=\d)(?=\d)", 
                    ","
                )
            ),
            ","
        ).cast("array<int>")
    
    df = df.withColumn("list", getEvenNumList(f.col("col2")))
    df.show()
    #+----+----+---------------+
    #|col1|col2|           list|
    #+----+----+---------------+
    #|   A|   8|[0, 2, 4, 6, 8]|
    #|   B|   7|   [0, 2, 4, 6]|
    #+----+----+---------------+
    
    df.printSchema()
    #root
    # |-- col1: string (nullable = true)
    # |-- col2: long (nullable = true)
    # |-- list: array (nullable = true)
    # |    |-- element: integer (containsNull = true)
    

    解释

    所需列表中的元素数是1加上 col2 除以2。(加1表示前导 0 )忽略 现在让我们 n 是地板 COL2 除以2。

    如果您将列表中的数字组合在一起(可以使用 str.join )的结果将由表达式给出:

    2*sum(i*10**(n-i) for i in range(1,n+1))
    

    使用wolfram alpha,可以为这个和计算一个闭式方程。

    一旦你有了这个数字,你就可以把它转换成一个以0开头的字符串。

    最后,我添加了一个逗号作为每个数字之间的分隔符,分割结果,并将其转换成一个整数数组。

    推荐文章