我有一个带有作业标题列的数据框,我想将其拆分为单独的列。由于本列中的字符串模式种类繁多,因此在对它们进行排序并将模式合成为下面的 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)'
目标:我想拆分,但也只有在匹配某些字符序列时才能拆分
first_job
) 应在第一个 ",
或 ',
之后进行second_job
) 应在第二次 ',
或第一次 ",
之后进行条件:
(Also
之后直到 )
的字符(参见上面的 xxxx
和 yyyy
)将替换 None
列中的 side_job
值< /li>
'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"'(?=,)|"(?=,)"
但我离做上述事情还很远。
答案 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”的正则表达式模式的回答