【问题标题】:Pyspark alter column with substringPyspark 使用子字符串更改列
【发布时间】:2018-03-26 18:53:53
【问题描述】:

Pyspark n00b...如何用其自身的子字符串替换列?我正在尝试从字符串的开头和结尾删除选定数量的字符。

from pyspark.sql.functions import substring
import pandas as pd
pdf = pd.DataFrame({'COLUMN_NAME':['_string_','_another string_']})
# this is what i'm looking for...
pdf['COLUMN_NAME_fix']=pdf['COLUMN_NAME'].str[1:-1] 

df = sqlContext.createDataFrame(pdf)
# following not working... COLUMN_NAME_fix is blank
df.withColumn('COLUMN_NAME_fix', substring('COLUMN_NAME', 1, -1)).show() 

这非常接近但略有不同Spark Dataframe column with last character of other column。然后是这个 LEFT and RIGHT function in PySpark SQL

【问题讨论】:

    标签: pyspark pyspark-sql


    【解决方案1】:

    接受的答案使用udf(用户定义的函数),它通常比本机火花代码慢(很多)。 Grant Shannon 的回答确实使用了本地 spark 代码,但正如 citynorman 在 cmets 中所指出的,对于可变字符串长度,这并不是 100% 清楚的。

    使用原生 spark 代码(无 udf)和可变字符串长度回答

    从pyspark中substr的文档中,我们可以看到参数:startPos和length可以是int或者Column类型(两者必须是相同类型)。所以我们只需要创建一个包含字符串长度的列并将其用作参数。

    import pyspark.sql.functions as F
    
    result = (
        df
        .withColumn('length', F.length('COLUMN_NAME'))
        .withColumn('fixed_in_spark', F.col('COLUMN_NAME').substr(F.lit(2), F.col('length') - F.lit(2)))
    )
    
    # result:
    +----------------+---------------+----+--------------+
    |     COLUMN_NAME|COLUMN_NAME_fix|size|fixed_in_spark|
    +----------------+---------------+----+--------------+
    |        _string_|         string|   8|        string|
    |_another string_| another string|  16|another string|
    +----------------+---------------+----+--------------+
    

    注意:

    • 我们使用 length - 2 是因为我们从第二个字符开始(并且需要直到倒数第二个字符)。
    • 我们需要使用F.lit,因为我们不能对Column 对象添加(或减去)数字。我们需要先将该数字转换为Column

    【讨论】:

      【解决方案2】:

      如果目标是从列名中删除“_”,那么我将使用列表推导:

      df.select(
          [ col(c).alias(c.replace('_', '') ) for c in df.columns ]
      )
      

      【讨论】:

        【解决方案3】:

        pyspark.sql.functions.substring(str, pos, len)

        当str为String类型时,子字符串从pos开始,长度为len;当str为Binary类型时,返回从pos开始,长度为len的字节数组切片

        在您的代码中,

        df.withColumn('COLUMN_NAME_fix', substring('COLUMN_NAME', 1, -1))
        1 is pos and -1 becomes len, length can't be -1 and so it returns null
        

        试试这个,(使用固定语法)

        from pyspark.sql.types import StringType
        from pyspark.sql.functions import udf
        
        udf1 = udf(lambda x:x[1:-1],StringType())
        df.withColumn('COLUMN_NAME_fix',udf1('COLUMN_NAME')).show()
        

        【讨论】:

          【解决方案4】:

          尝试:

          df.withColumn('COLUMN_NAME_fix', df['COLUMN_NAME'].substr(1, 10)).show()
          

          其中 1 = 字符串中的起始位置,并且 10 = 从起始位置开始包含的字符数(包括)

          【讨论】:

          • 如果长度是动态的呢?
          • 使用:df['COLUMN_NAME'].substr(startPos, strLength) 其中startPos是变量的起始位置,strLength 是要包含的字符数的可变长度
          • 是的,如果strLength 像我上面的示例那样在样本之间发生变化,则会失败
          猜你喜欢
          • 2021-12-13
          • 2021-02-27
          • 1970-01-01
          • 2019-12-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多