我使用Spark RDD和DataFrame创建了文本文件的字数,但答案略有不同。我正在使用的数据可用here。 为什么答案不同?
from pyspark.sql.functions import col, trim, lower, regexp_replace, explode, split, length
from pyspark.sql import Row
from nltk.corpus import stopwords
stopwords = stopwords.words('english')
def clean1(line):
return trim(lower(regexp_replace(line, '[^a-zA-Z0-9\s]','')))
df1 = (spark.read.text("Quran.txt")
.select(clean1('value').alias('line'))
.select(explode(split('line', ' ')).alias('word'))
.filter(length(col("word")) > 0)
.filter(~col('word').isin(stopwords))
.groupBy('word').count()
.orderBy('count', ascending = False)
)
df1.show(10)
import re
def cleanline(line):
return re.sub('[^a-zA-Z0-9\s]', '', line).lower().strip()
df2 = (sc.textFile('Quran.txt')
.map(lambda x: cleanline(x))
.flatMap(lambda x: x.split(' '))
.filter(lambda x: len(x) > 0)
.filter(lambda x: x not in stopwords)
.map(lambda x: (x, 1))
.reduceByKey(lambda a, b: a + b)
.sortBy(lambda x: -x[1])
.map(lambda x: Row(word = x[0], count = x[1]))
.toDF()
.select(['word','count'])
)
df2.show(10)
我发现如果我在' [^ a-zA-Z0-9 \ s]'更改DataFrame部分中的正则表达式到' [^ a-zA-Z0-9]',答案变得相同。这两个正则表达式是不一样的吗?
答案 0 :(得分:4)
如果你看一下trim
'ltrim': 'Trim the spaces from left end for the specified string value.',
'rtrim': 'Trim the spaces from right end for the specified string value.',
'trim': 'Trim the spaces from both ends for the specified string column.',
表示修剪仅删除空格而不删除标签(\ t) 。但是在下面的某些行中有标签,trim
函数不会将其删除。
God could destroy him if He chose, v. 19 (488)
这就是上面一行中god
的原因不计算在前面有标签。虽然strip
()函数删除了所有空格,包括前面的标签。
类似的情况也适用于其他计数。
因此,定义udf
函数可以使用strip
() python函数是您的解决方案。
from pyspark.sql import functions as F
from pyspark.sql import types as T
def stripUdf(x):
return x.strip()
callStripUdf = F.udf(stripUdf, T.StringType())
def clean1(line):
return callStripUdf(F.trim(F.lower(F.regexp_replace(line, '[^a-zA-Z0-9\s]',''))))
正如您所提到的,从[^a-zA-Z0-9\s]
更改为[^a-zA-Z0-9 ]
解决了这个问题,因为 \ s 意味着所有空白包括 tab(\ t),因此在应用trim
之前,更改将标签替换为空字符。
我希望答案很有帮助