cột trích xuất tia lửa từ chuỗi

Nov 05 2020

Cần trợ giúp trong việc phân tích cú pháp một chuỗi, nơi chứa các giá trị cho từng thuộc tính. dưới đây là chuỗi mẫu của tôi ...

otherPartofString Name=<Series VR> Type=<1Ac4> SqVal=<34> conn ID=<2>

đôi khi, chuỗi có thể bao gồm các giá trị khác với dấu phân cách khác như

otherPartofString Name=<Series X> Type=<1B3> SqVal=<34> conn ID=<2> conn Loc=sfo dest=chc bridge otherpartofString.. 

các cột đầu ra sẽ là

Name      | Type | SqVal | ID | Loc  | dest 
-------------------------------------------
Series VR | 1Ac4 | 34    | 2  | null | null
Series X  | 1B3  | 34    | 2  | sfo  | chc 

Trả lời

2 jxc Nov 05 2020 at 20:39

Như chúng ta đã thảo luận, để sử dụng hàm str_to_map trên dữ liệu mẫu của bạn, chúng ta có thể thiết lập pairDelimkeyValueDelim như sau:

pairDelim: '(?i)>? *(?=Name|Type|SqVal|conn ID|conn Loc|dest|$)'
keyValueDelim: '=<?'

Trong đó pariDelim không phân biệt chữ hoa chữ thường (?i)với tùy chọn >theo sau là không hoặc nhiều phím cách, sau đó là một trong các khóa được xác định trước (chúng tôi sử dụng '|'.join(keys)để tạo động) hoặc phần cuối của ký tự neo $. keyValueDelim là một '=' với một tùy chọn <.

from pyspark.sql import functions as F

df = spark.createDataFrame([                                               
   ("otherPartofString Name=<Series VR> Type=<1Ac4> SqVal=<34> conn ID=<2>",),   
   ("otherPartofString Name=<Series X> Type=<1B3> SqVal=<34> conn ID=<2> conn Loc=sfo dest=chc bridge otherpartofString..",)
],["value"])

keys = ["Name", "Type", "SqVal", "conn ID", "conn Loc", "dest"]

# add the following conf for Spark 3.0 to overcome duplicate map key ERROR
#spark.conf.set("spark.sql.mapKeyDedupPolicy", "LAST_WIN")

df.withColumn("m", F.expr("str_to_map(value, '(?i)>? *(?={}|$)', '=<?')".format('|'.join(keys)))) \
    .select([F.col('m')[k].alias(k) for k in keys]) \
    .show()
+---------+----+-----+-------+--------+--------------------+
|     Name|Type|SqVal|conn ID|conn Loc|                dest|
+---------+----+-----+-------+--------+--------------------+
|Series VR|1Ac4|   34|      2|    null|                null|
| Series X| 1B3|   34|      2|     sfo|chc bridge otherp...|
+---------+----+-----+-------+--------+--------------------+

Chúng tôi sẽ cần thực hiện một số xử lý hậu kỳ đối với các giá trị của khóa được ánh xạ cuối cùng, vì không có liên kết hoặc mẫu nào để phân biệt chúng với văn bản không liên quan khác (đây có thể là sự cố vì nó có thể xảy ra trên bất kỳ khóa nào), vui lòng cho Tôi biết nếu bạn có thể chỉ định bất kỳ mẫu nào.

Chỉnh sửa: Nếu việc sử dụng bản đồ kém hiệu quả hơn đối với tìm kiếm không phân biệt chữ hoa chữ thường vì nó yêu cầu một số xử lý trước tốn kém, hãy thử cách sau:

ptn = '|'.join(keys)
df.select("*", *[F.regexp_extract('value', r'(?i)\b{0}=<?([^=>]+?)>? *(?={1}|$)'.format(k,ptn), 1).alias(k) for k in keys]).show()

Trong trường hợp dấu ngoặc nhọn <>chỉ được sử dụng khi các giá trị hoặc khóa liền kề tiếp theo của chúng chứa bất kỳ ký tự không phải từ nào, nó có thể được đơn giản hóa bằng một số xử lý trước:

df.withColumn('value', F.regexp_replace('value','=(\w+)','=<$1>')) \
    .select("*", *[F.regexp_extract('value', r'(?i)\b{0}=<([^>]+)>'.format(k), 1).alias(k) for k in keys]) \
    .show()

Chỉnh sửa-2: đã thêm một từ điển để xử lý các bí danh chính:

keys = ["Name", "Type", "SqVal", "ID", "Loc", "dest"]

# aliases are case-insensitive and added only if exist
key_aliases = {
    'Type': [ 'ThisType', 'AnyName' ],
    'ID': ['conn ID'],
    'Loc': ['conn Loc']
}

# set up regex pattern for each key differently
key_ptns = [ (k, '|'.join([k, *key_aliases[k]]) if k in key_aliases else k) for k in keys ]  
#[('Name', 'Name'),
# ('Type', 'Type|ThisType|AnyName'),
# ('SqVal', 'SqVal'),
# ('ID', 'ID|conn ID'),
# ('Loc', 'Loc|conn Loc'),
# ('dest', 'dest')]  

df.withColumn('value', F.regexp_replace('value','=(\w+)','=<$1>')) \
    .select("*", *[F.regexp_extract('value', r'(?i)\b(?:{0})=<([^>]+)>'.format(p), 1).alias(k) for k,p in key_ptns]) \
    .show()
+--------------------+---------+----+-----+---+---+----+
|               value|     Name|Type|SqVal| ID|Loc|dest|
+--------------------+---------+----+-----+---+---+----+
|otherPartofString...|Series VR|1Ac4|   34|  2|   |    |
|otherPartofString...| Series X| 1B3|   34|  2|sfo| chc|
+--------------------+---------+----+-----+---+---+----+