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
答案 0 :(得分:7)
pyspark.sql.functions.substring(str,pos,len)
子串从pos开始,当str是String类型时长度为len,或者返回以字节开头的字节数组的片段,当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
试试这个,(使用固定语法)
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()
答案 1 :(得分:1)
可接受的答案使用udf
(用户定义的函数),它通常比本机Spark代码慢很多。格兰特·香农(Grant Shannon)的答案的确使用了本地的火花代码,但正如citynorman的评论所指出的那样,对于可变长度的字符串,它的工作方式还不是100%清楚。
具有本机火花代码(无udf)和可变字符串长度的答案
从pyspark中substr的文档中,我们可以看到参数:startPos和length可以是int
或Column
类型(两者必须是同一类型)。因此,我们只需要创建一个包含字符串长度的列并将其用作参数即可。
import pyspark.sql.functions as sf
result = (
df
.withColumn('length', sf.length('COLUMN_NAME'))
.withColumn('fixed_in_spark', col('COLUMN_NAME').substr(sf.lit(2), col('length') - sf.lit(2)))
)
# result:
+----------------+---------------+----+--------------+
| COLUMN_NAME|COLUMN_NAME_fix|size|fixed_in_spark|
+----------------+---------------+----+--------------+
| _string_| string| 8| string|
|_another string_| another string| 16|another string|
+----------------+---------------+----+--------------+
注意:
sf.lit
,因为我们无法向Column
对象添加(或减去)数字。我们需要先将该数字转换为Column
。答案 2 :(得分:0)
尝试:
df.withColumn('COLUMN_NAME_fix', df['COLUMN_NAME'].substr(1, 10)).show()
其中1 =字符串中的起始位置和 10 =从起始位置(包括)开始包含的字符数
答案 3 :(得分:0)
如果目标是从列名中删除“ _”,那么我将使用列表理解:
df.select(
[ col(c).alias(c.replace('_', '') ) for c in df.columns ]
)