蟒蛇 |正则表达式 |拆分行;不是列
Posted
技术标签:
【中文标题】蟒蛇 |正则表达式 |拆分行;不是列【英文标题】:Python | Regex | Split Rows; Not columns 【发布时间】:2018-08-26 06:09:18 【问题描述】:我有一个包含 5 个嵌套行的数据框(全部包含以下数据)
1ItWB (NL)$327,481,7484,148$123,403,4194,1039/8/172The
ExorcistWB$232,906,145-n/a-12/26/733Get
OutUni.$176,040,6653,143$33,377,0602,7812/24/174The Blair Witch
ProjectArt.$140,539,0992,538$1,512,054277/16/995The ConjuringWB
(NL)$137,400,1413,115$41,855,3262,9037/19/136Paranormal
ActivityPar.$107,918,8102,712$77,873129/25/097Interview with the
VampireWB$105,264,6082,604$36,389,7052,60411/11/94
我想要做的是拆分成新的行;不是列。
我尝试过这样的事情:
df["Box_Office"].str.split(r'([\d][A-Z][a-z]*)', expand=True)
df["Box_Office"].str.split(r'([\d][A-Z][a-z]*)', expand=True).melt()
df["Box_Office"].str.split(r'([\d][A-Z][a-z]*)', expand=True).stack().to_frame()
正则表达式在每个新等级处分裂(例如:2The、3Get、4The)。我只希望拆分创建新行,而不是列。正则表达式需要一些工作,但我很高兴自己完成这些工作。
我可以融化数据框来创建行,但是清理变得很耗时(如果没有其他方法,很高兴沿着这条路走下去)。
Stacking 更接近,但它分成单独的行(这自然与我的正则表达式有关)。这感觉最接近,但我找不到一个正则表达式模式来捕捉这个[还]。
理想的结果如下,但我真正需要的只是标题和总价
Rank Title Studio Gross Theatres Date
1 IT WB $327,481,748 4,138 9/8/17
2 The Exorcist WB $232,906,145 NA 12/26/73
以下内容更接近一点
df["Box_Office"].str.split(r'(\$[0-9,/]*)', expand=True).stack().to_frame()
提取或拆分是否可以跨行而不是跨列向下扩展?
【问题讨论】:
Arrgghh,你的方法不好!您的数据来自一个网站(可能是boxofficemojo.com)。使用 html 解析器 (beautifulsoup) 来提取已经结构化的信息。使用 html 结构,而不是尝试使用正则表达式拆分连接的文本。 你好 - 我使用 BeautifulSoup 来获取这些数据 - 这是返回的结构。如果有帮助,我可以发送我的代码吗? 好的,不是为每个 tr 标签(连接所有文本节点)提取文本内容,而是遍历 td 标签以分别获取每个 tr 标签的每个信息。 当然,您可以在问题中添加其他信息。但是,请注意只发布代码中有趣的部分(如果代码很长,则不要发布所有代码)。 【参考方案1】:我会这样做:
(?P<title>[A-Z](?:(?!WB|Par|Art|Uni)[-\sA-Za-z])+)
(?P<studio>WB|Par|Art|Uni)
[^$]*
(?P<gross>\$\d+(?:,\d3)*)
(?P<theatres>(?:\d+(?:,\d3)*)|-n/a-)
[$,\d]*?
(?P<date>(?:1[0-2]|[1-9])/\d1,2/\d2)
Python
中的哪个是:
import pandas as pd, re
junk = """
1ItWB (NL)$327,481,7484,148$123,403,4194,1039/8/172The
ExorcistWB$232,906,145-n/a-12/26/733Get
OutUni.$176,040,6653,143$33,377,0602,7812/24/174The Blair Witch
ProjectArt.$140,539,0992,538$1,512,054277/16/995The ConjuringWB
(NL)$137,400,1413,115$41,855,3262,9037/19/136Paranormal
ActivityPar.$107,918,8102,712$77,873129/25/097Interview with the
VampireWB$105,264,6082,604$36,389,7052,60411/11/94"""
rx = re.compile(r'''
(?P<Title>[A-Z](?:(?!WB|Par|Art|Uni)[-\sA-Za-z])+)
(?P<Studio>WB|Par|Art|Uni)
[^$]*
(?P<Gross>\$\d+(?:,\d3)*)
(?P<Theatres>(?:\d+(?:,\d3)*)|-n/a-)
[$,\d]*?
(?P<Date>(?:1[0-2]|[1-9])/\d1,2/\d2)''', re.VERBOSE)
def replacer(d):
d['Title'] = d['Title'].replace('\n', ' ')
return d
records = (replacer(m.groupdict()) for m in rx.finditer(junk))
df = pd.DataFrame(records)
# reorder the columns if necessary
df = df[['Title', 'Studio', 'Gross', 'Theatres', 'Date']]
print(df)
这产生
Title Studio Gross Theatres Date
0 It WB $327,481,748 4,148 9/8/17
1 The Exorcist WB $232,906,145 -n/a- 12/26/73
2 Get Out Uni $176,040,665 3,143 12/24/17
3 The Blair Witch Project Art $140,539,099 2,538 7/16/99
4 The Conjuring WB $137,400,141 3,115 7/19/13
5 Paranormal Activity Par $107,918,810 2,712 9/25/09
6 Interview with the Vampire WB $105,264,608 2,604 11/11/94
见a demo for the expression on regex101.com。
至于你原来的问题:你可以提取列,然后转置数据框(比如把它转过来)。但是,您首先从哪里获得这些数据?从什么地方刮下来的?您可能需要重新考虑这一步!
【讨论】:
电影《走出去》的日期有问题。日期应该是“2/24/17”,但出来的是“12/24/17”。还错过了电影《布莱尔女巫计划》。我建议another regex。 这很有效(非常好的正则表达式 - 也是) - 从中学到了很多东西。假设“详细”允许更简洁的代码和忽略的空格?这真的很方便。我确实有一个问题 - 这段代码实际上在做什么 '(replacer(m.groupdict()) for m in rx.finditer(junk))' - 它只是一个遍历文本的列表理解吗?不确定 groupdict 或 finditer 变量在做什么 - 任何帮助将不胜感激! @AndreiOdegov:显然有12/24/17
和The Blai Witch Project
(3)。
@Jan,很抱歉 id 为 3 的记录。但 id 为 2 的记录包含 $33,377,060;2,781;2/24/17
。对吗?
@AndreiOdegov:是的,当涉及到日期部分时,整个表达式是模棱两可的,我会首先更改抓取机制!以上是关于蟒蛇 |正则表达式 |拆分行;不是列的主要内容,如果未能解决你的问题,请参考以下文章
(Oracle) SQL 中的正则表达式将日期/时间拆分为单独的日期和时间列