Pyspark用子串改变列

cit*_*man 3 pyspark pyspark-sql

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() 
Run Code Online (Sandbox Code Playgroud)

这是非常接近但与其他列的最后一个字符略有不同的Spark Dataframe列.然后在PySpark SQL中有这个 LEFT和RIGHT函数

Gra*_*non 17

尝试:

df.withColumn('COLUMN_NAME_fix', df['COLUMN_NAME'].substr(1, 10)).show()
Run Code Online (Sandbox Code Playgroud)

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

  • 是的,如果 `strLength` 在样本之间发生变化,这会失败,如我上面的例子 (3认同)
  • 如果长度是动态的怎么办? (2认同)

Sur*_*esh 11

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

子串从pos开始,当str是String类型时长度为len,或者返回以字节为单位从pos开始的字节数组的片段,当str为二进制类型时,长度为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
Run Code Online (Sandbox Code Playgroud)

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

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()
Run Code Online (Sandbox Code Playgroud)


Wil*_*lem 6

接受的答案使用udf(用户定义的函数),它通常(比原生火花代码)慢得多。Grant Shannon 的回答确实使用了原生 spark 代码,但正如 citynorman 的评论中所指出的,对于可变字符串长度如何工作并不是 100% 清楚。

使用本机火花代码(无 udf)和可变字符串长度回答

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

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|
+----------------+---------------+----+--------------+
Run Code Online (Sandbox Code Playgroud)

笔记:

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