蟒蛇 |正则表达式 |拆分行;不是列

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/17The Blai Witch Project (3)。 @Jan,很抱歉 id 为 3 的记录。但 id 为 2 的记录包含 $33,377,060;2,781;2/24/17。对吗? @AndreiOdegov:是的,当涉及到日期部分时,整个表达式是模棱两可的,我会首先更改抓取机制!

以上是关于蟒蛇 |正则表达式 |拆分行;不是列的主要内容,如果未能解决你的问题,请参考以下文章

(Oracle) SQL 中的正则表达式将日期/时间拆分为单独的日期和时间列

Pandas 正则表达式拆分字符和组

拆分字符串,提取并添加到另一列正则表达式 BIGQUERY

根据字符串(正则表达式)将一行拆分为更多行

Python - 正则表达式将数据框中的一列拆分为 2 [重复]

使用正则表达式用单冒号而不是双冒号拆分