拆分字符串并附加多个条件

时间:2021-03-21 17:38:47

标签: python regex string dataframe split

我有一个带有作业标题列的数据框,我想将其拆分为单独的列。由于本列中的字符串模式种类繁多,因此在对它们进行排序并将模式合成为下面的 3 种模式之前,我将它们过滤为唯一的。

我的假设是,如果它可以按照我想要的方式处理这 3 个字符串,它也将处理该数据帧中的所有其他字符串。

数据

print(df['split_these_jobtitles'])
0  '- a a (a a), a a', '- a a (Also xxxx), a a', '- a a (a a), a a', 'a a (a, a a)', 'a a, a a', 'a a'       
1  "a a, a' a", 'a a, a 5 (a, a)', 'a a'                                                               
2  'Chair, a (a & a), a a, a', 'Chair, a, a & a-a - a -a' 'a (a a) (a, a)', "a'a a & a (Also yyyy) (a, a) ", 'a (a, a) (a a)'

目标:我想拆分,但也只有在匹配某些字符序列时才能拆分

  1. 第一次拆分 (first_job) 应在第一个 ", ', 之后进行
  2. 第二次分割 (second_job) 应在第二次 ', 或第一次 ", 之后进行

条件:

  1. (Also 之后直到 ) 的字符(参见上面的 xxxxyyyy)将替换 None 列中的 side_job 值< /li>
  2. 'Chair, 后面的字符直到下一个 ', 将替换 None 列中的 chair_job

这是成功拆分后数据框的样子:

<头>
first_job second_job side_job chair_job
a a (a a), a a a a, a a, a a (a a), a a a a (a, a a) a a, a a, a a xxxx
a a, a' a a a, a 5 (a, a) a a
a (a a) (a, a) a'a a & a (a, a) a (a, a) (a a) yyyy Chair, a (a & a), a a, a, Chair, a, a & a-a - a -a

问题还在于我对正则表达式真的很陌生,因为我过去曾尝试避免使用它。我认为此任务可以使用 re.split(),对吧,因为我不会在零宽度上拆分?

我已经把双引号或单引号分开了

re.split(r"'(?=,)|"(?=,)"

但我离做上述事情还很远。

2 个答案:

答案 0 :(得分:0)

据我了解您的任务。拆分每一行是有道理的。为了获得括号内的主席和副业,我可以建议这些正则表达式:

match_side_job = re.search(r'\(Also (?P<side_job>\w*?)\)')
match_chair =  re.search(r'?P<chair>Chair.*?),')
 
match_side_job.groupdict('side_job')
yyyyy
match_chair.groupdict('chair')
Chair abcde

可能只适用于部分分割线。

答案 1 :(得分:0)

查看您的示例列,我不知道只有“干净”正则表达式的解决方案。您需要提取和删除匹配项(“用空替换”)。

我建议使用基于 .apply() 的解决方案。这允许您使用函数来捕获数据清理所需的相当复杂的逻辑。

我们还可以使用 re.sub(Also \w) 模式的任何匹配项替换为空。

以下是这些如何协同工作的简单示例(但绝不是完美的):

import pandas as pd
import re


a = '- a a (a a), a a', '- a a (Also xxxx), a a', '- a a (a a), a a', 'a a (a, a a)', 'a a, a a', 'a a'       
b =   "a a, a' a", 'a a, a 5 (a, a)', 'a a'                                                               
c =  'Chair, a (a & a), a a, a', 'Chair, a, a & a-a - a -a' 'a (a a) (a, a)', "a'a a & a (Also yyyy) (a, a) ", 'a (a, a) (a a)'


df = pd.DataFrame({"split_these_jobtitles": [a, b, c]})
print(df["split_these_jobtitles"])


def extract_jobs(row):
    # Store a short temporary variable name
    split_text = row["split_these_jobtitles"]

    # Compile a regex to find the side_job and find it
    match_side_job = re.compile(r"\(Also (?P<side_job>\w*?)\)")
    side_job = match_side_job.search(" ".join(split_text))
    side_job = side_job.groupdict("side_job")["side_job"] if side_job else None # ensure None if no matches

    # Get the chair job and remove it from our options
    chair_jobs = [txt for txt in split_text if txt.startswith("Chair,")]
    chair_jobs = chair_jobs if chair_jobs else None # ensure None if no chair jobs
    split_text = [txt for txt in split_text if txt not in chair_jobs]

    # Remove any side_job matches from the split_text list
    split_text = [match_side_job.sub("", txt) for txt in split_text]

    first_job = split_text[0]
    second_job = split_text[1]
    return first_job, second_job, side_job, chair_jobs


df[["first_job", "second_job", "side_job", "chair_jobs"]] = df.apply(
    lambda row: extract_jobs(row), axis="columns", result_type="expand"
)
print(df)

这给了我以下内容:

0    (- a a (a a), a a, - a a (Also xxxx), a a, - a...
1                    (a a, a' a, a a, a 5 (a, a), a a)
2    (Chair, a (a & a), a a, a, Chair, a, a & a-a -...
Name: split_these_jobtitles, dtype: object
                               split_these_jobtitles           first_job       second_job side_job                                         chair_jobs
0  (- a a (a a), a a, - a a (Also xxxx), a a, - a...    - a a (a a), a a      - a a , a a     xxxx                                                 []
1                  (a a, a' a, a a, a 5 (a, a), a a)           a a, a' a  a a, a 5 (a, a)     None                                                 []
2  (Chair, a (a & a), a a, a, Chair, a, a & a-a -...  a'a a & a  (a, a)    a (a, a) (a a)     yyyy  [Chair, a (a & a), a a, a, Chair, a, a & a-a -...

对于正则表达式的帮助,我建议使用 https://www.debuggex.com/https://regex101.com/ 之类的网站。帮助您想象正在发生的事情并了解一些常见的“令牌”。

感谢 @samusa 之前对“side_job”的正则表达式模式的回答