我有一個資料框,其中包含一個包含不同長度文本的字串列,然后我有一個陣列列,其中每個元素都是一個結構,在文本列中具有指定的單詞、索引、起始位置和結束位置。我想替換文本列中的單詞,即陣列中的單詞。
它看起來像這樣:
- id:integer
- text:string
- text_entity:array
- element:struct
- word:string
- index:integer
- start:integer
- end:integer
text 示例可能是:
"I talked with Christian today at Cafe Heimdal last Wednesday"
text_entity 示例可能是:
[{"word": "Christian", "index":4, "start":14, "end":23}, {"word": "Heimdal", "index":8, "start":38, "end":45}]
然后我想將text上述索引處的單詞更改為:
"I talked with (BLEEP) today at Cafe (BLEEP) last Wednesday"
我最初的方法是分解陣列然后做 a regex_replace,但隨后出現了收集文本并合并它們的問題。而且似乎需要很多操作。而且我不想使用 UDF,因為性能非常重要。regex_replace還有一個問題是它可能匹配子字串,那是不行的。因此,理想情況下使用索引、開始或結束。
uj5u.com熱心網友回復:
在具有拆分列的陣列上使用aggregate函式作為初始值,如下所示:text_entitytext
from pyspark.sql import functions as F
jsonSting = """{"id":1,"text":"I talked with Christian today at Cafe Heimdal last Wednesday","text_entity":[{"word":"Christian","index":4,"start":14,"end":23},{"word":"Heimdal","index":8,"start":38,"end":45}]}"""
df = spark.read.json(spark.sparkContext.parallelize([jsonSting]))
df1 = df.withColumn(
"text",
F.array_join(
F.expr(r"""aggregate(
text_entity,
split(text, " "),
(acc, x) -> transform(acc, (y, i) -> IF(i=x.index, '(BLEEP)', y))
)"""),
" "
)
)
df1.show(truncate=False)
# --- ---------------------------------------------------------- ----------------------------------------------
#|id |text |text_entity |
# --- ---------------------------------------------------------- ----------------------------------------------
#|1 |I talked with (BLEEP) today at Cafe (BLEEP) last Wednesday|[{23, 4, 14, Christian}, {45, 8, 38, Heimdal}]|
# --- ---------------------------------------------------------- ----------------------------------------------
uj5u.com熱心網友回復:
我使用regexp_replace想出了這個答案,但是使用 regex replace 的問題是它會替換所有出現的地方,這不是本意,因為一個單詞可能會在文本中多次出現,并且只有一些出現應該是“嗶嗶”
df = df.withColumn("temp_entities", F.expr(f"transform(text_entity, (x, i) -> x.word)")) \
.withColumn("temp_entities", F.array_distinct("temp_entities")) \
.withColumn("regex_expression", F.concat_ws("|", "temp_entities")) \
.withColumn("regex_expression", F.concat(F.lit("\\b("), F.col("regex_expression"), F.lit(")\\b"))) \
.withColumn("text", F.when(F.size("text_entity") > 0, F.expr("regexp_replace(text, regex_expression, '(BLEEP)')")).otherwise(F.col(text)))
它洗掉重復項,并且僅在存在至少 1 個物體時才應用regexp_replace 。可能不是最優雅的解決方案,并且會“嗶”所有出現的單詞。理想情況下應該使用該位置。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/418180.html
標籤:
上一篇:Spark:如何將間隔除以間隔
