同时使用 f-string 和 raw string

Using f-string and raw string at same time

我有这样一个数据框:

           p          q
0      jdkdn  01JAN2020
1  01JAN2020   hdk789dj
2      783i3  01FEB2020

我正在尝试用 01-01-2020 替换 01JAN2020,基本上是 alphabetical month namenumeric month number。我不知道这些 date 在哪里,意思是在任何列和任何行中。我曾尝试仅使用 df.replace 来完成此操作,但原始字符串有问题,我也想使用 f-string。 这是我的尝试:

import pandas as pd
import re

df=pd.DataFrame({"p":["jdkdn","01JAN2020","783i3"],"q":["01JAN2020","hdk789dj","01FEB2020"]})

months = {'JAN': '01', 'FEB': '02'}
#All 12 months but for test I am using just 2

df.replace(r'(\d{2})('+'|'.join(months)+')(\d{4})',r"-"+

f"{{months[\2]}}" # Here I am trying to do main things

+r"-",regex=True,inplace=True)
print(df)
"""
                       p                      q
0                  jdkdn  01-{months[JAN]}-2020
1  01-{months[JAN]}-2020               hdk789dj
2                  783i3  01-{months[FEB]}-2020
"""

fr"{{months[\2]}}"
"""
                      p                     q
0                 jdkdn  01-{months[]}-2020
1  01-{months[]}-2020              hdk789dj
2                 783i3  01-{months[]}-2020
"""

rf"{months[]}" and rf"{months[\2]}"
"""
SyntaxError: f-string expression part cannot include a backslash
"""

想法:
我们可以像 (?(<month name>)<number>) 一样使用 regex if 吗?pandas 中任何可以检测任何 01JAN2020 的函数将其替换为 01-01-2020

预期输出为:

           p           q
0      jdkdn  01-01-2020
1 01-01-2020    hdk789dj
2      783i3  01-02-2020

您可以使用 pandas 海峡。替换,只需创建一个带有名称和替换的模式,然后使用 transform 将其应用于所有列:

pat = r"(?P<day>\d+)(?P<month>[A-Z]+)(?P<year>\d+)"
repl = lambda m: f"{m.group('day')}-{months[m.group('month')]}-{m.group('year')}"

df.transform(lambda x: x.str.replace(pat, repl, regex=True))
 
            p           q
0       jdkdn  01-01-2020
1  01-01-2020    hdk789dj
2       783i3  01-02-2020

注意,对于字符串,如果你想要更高的性能,你可以把它写在python之内并应用。您可以为此使用 re.sub,它应该会带来明显的改进(请测试):

df.applymap(lambda x: re.sub(pat, repl, x))

如果您的数据是重复的,一种有效的方法是转换为分类并将字符串修改应用于类别;那应该会更快。

请注意,在 python 中,pandas 字符串函数隐含地涵盖了空值,您的代码应该涵盖这些可能的情况。