簡體   English   中英

Python 字符串匹配 Spark dataframe

[英]Python string matching with Spark dataframe

我有火花 dataframe

id  | city  | fruit | quantity
-------------------------
0   |  CA   | apple | 300
1   |  CA   | appel | 100
2   |  CA   | orange| 20
3   |  CA   | berry | 10

我想得到水果是appleorange的行。 所以我使用 Spark SQL:

SELECT * FROM table WHERE fruit LIKE '%apple%' OR fruit LIKE '%orange%';

它返回

id  | city  | fruit | quantity
-------------------------
0   |  CA   | apple | 300
2   |  CA   | orange| 20

但它應該返回

id  | city  | fruit | quantity
-------------------------
0   |  CA   | apple | 300
1   |  CA   | appel | 100
2   |  CA   | orange| 20

因為第 1 行只是一個拼寫錯誤。

所以我打算使用fuzzywuzzy進行字符串匹配。 我知道

import fuzzywuzzy
from fuzzywuzzy import fuzz
from fuzzywuzzy import process

print(fuzz.partial_ratio('apple', 'apple')) -> 100
print(fuzz.partial_ratio('apple', 'appel')) -> 83

但我不確定如何將此應用於 dataframe 中的列以獲取相關行

由於您有興趣將模糊匹配實現為過濾器,因此您必須首先確定您希望匹配的相似程度的閾值。

方法一

對於您的fuzzywuzzy導入,出於本演示的目的,這可能是80 (根據您的需要進行調整)。 然后,您可以實現一個 udf 來應用您導入的模糊邏輯代碼,例如

from pyspark.sql import functions as F
from pyspark.sql import types as T

F.udf(T.BooleanType())
def is_fuzzy_match(field_value,search_value, threshold=80):
    from fuzzywuzzy import fuzz
    return fuzz.partial_ratio(field_value, search_value) > threshold

然后在您的 dataframe 上應用您的 udf 作為過濾器

df = (
    df.where(
          is_fuzzy_match(F.col("fruit"),F.lit("apple"))  | 
          is_fuzzy_match(F.col("fruit"),F.lit("orange"))  
    )
)

方法二:推薦

但是,在 spark 上執行 udfs 可能會很昂貴,並且 spark 已經實現了levenshtein function,這在這里也很有用。 您可能會開始閱讀更多關於levenshtein 距離如何完成模糊匹配的信息。

使用這種方法,您的代碼看起來像使用下面的閾值3

from pyspark.sql import functions as F

df = df.where(
    (
        F.levenshtein(
            F.col("fruit"),
            F.lit("apple")
        ) < 3
     ) |
     (
        F.levenshtein(
            F.col("fruit"),
            F.lit("orange")
        ) < 3
     ) 
)

df.show()
+---+----+------+--------+
| id|city| fruit|quantity|
+---+----+------+--------+
|  0|  CA| apple|     300|
|  1|  CA| appel|     100|
|  2|  CA|orange|      20|
+---+----+------+--------+

出於調試目的,levenshtein 的結果已包含在下面

df.withColumn("diff",
    F.levenshtein(
        F.col("fruit"),
        F.lit("apple")
    )
).show()
+---+----+------+--------+----+
| id|city| fruit|quantity|diff|
+---+----+------+--------+----+
|  0|  CA| apple|     300|   0|
|  1|  CA| appel|     100|   2|
|  2|  CA|orange|      20|   5|
|  3|  CA| berry|      10|   5|
+---+----+------+--------+----+

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM