如何从 Python 中的文本中提取 2d 年份?
How to extract 2d year from text in Python?
我试图从 Pandas DataFrame 的一列中的短文本中提取出生年份和死亡年份:
firstname lastname (1937-2015)
我用这个代码得到了第一年:
data = re.findall(r'\d+', txt)
if len(data) > 0 :
data = float(data[0])
if data >= 1800 and data <= 2021 :
return data
return None
但我无法从文本中提取第二年。
例如,当我将 data[0]
更改为 data[1]
时,出现错误消息“list index out of range”
您可以定义2个捕获组并检查它们
df = pd.DataFrame(
{'txt': ['firstname lastname (1937-2015)', 'firstname lastname (1780-1820)',
'firstname lastname (1945-?)', 'firstname lastname (1980-2022)']})
df[['birth', 'death']] = df['txt'].str.extract(r'(\d+)-(\d+|\?)').replace({'?': None}).astype(float). \
applymap(lambda x: x if 1800 <= x <= 2021 else None)
print(df)
输出:
txt birth death
0 firstname lastname (1937-2015) 1937.0 2015.0
1 firstname lastname (1780-1820) NaN 1820.0
2 firstname lastname (1945-?) 1945.0 NaN
3 firstname lastname (1980-2022) 1980.0 NaN
使用 Series.str.extract
提取 Pandas 中第二年(从 1800 到 2099)的通用正则表达式解决方案,您可以利用
import pandas as pd
df = pd.DataFrame({'col':['firstname lastname (1937-2015)']})
yr = r'(?:1[89][0-9]{2}|20[01][0-9]|202[01])'
df['second_year'] = df['col'].str.extract(fr'(?s)(?<!\d){yr}(?!\d).*?({yr})(?!\d)')
# => df['second_year']
# 0 2015
# Name: second_year, dtype: object
参见regex demo。 详情:
(?s)
- .
现在跨行匹配
(?<!\d)
- 左侧数字边界
(?:1[89][0-9]{2}|20[01][0-9]|202[01])
- 从 1800 年到 2021 年
(?!\d)
- 右手数字边界
.*?
- 任何文本,尽可能少的字符
(1[89][0-9]{2}|20[01][0-9]|202[01])
- 第 1 组(Series.str.extract
的实际 return 结果):1800 到 2021
(?!\d)
- 右手数字边界
在这个具体案例中,一个简单的
df['second_year'] = df['col'].str.extract(r'.*-(\d{4})')
就足够了:任何文本(尽可能多的字符而不是换行符),然后是 -
和捕获到第 1 组的四位数字。
参见 this regex demo。
使用正则表达式查找从和到子短语的年份,然后拆分它并为第二年编制索引。您可以在数据框中使用它申请分配给列
txt="firstname lastname (1937-2015)"
pattern='(\d{4}\-\d{4})+'
matches=re.findall(pattern,txt)
print(matches[0].split('-')[1])
输出
2015
我试图从 Pandas DataFrame 的一列中的短文本中提取出生年份和死亡年份:
firstname lastname (1937-2015)
我用这个代码得到了第一年:
data = re.findall(r'\d+', txt)
if len(data) > 0 :
data = float(data[0])
if data >= 1800 and data <= 2021 :
return data
return None
但我无法从文本中提取第二年。
例如,当我将 data[0]
更改为 data[1]
时,出现错误消息“list index out of range”
您可以定义2个捕获组并检查它们
df = pd.DataFrame(
{'txt': ['firstname lastname (1937-2015)', 'firstname lastname (1780-1820)',
'firstname lastname (1945-?)', 'firstname lastname (1980-2022)']})
df[['birth', 'death']] = df['txt'].str.extract(r'(\d+)-(\d+|\?)').replace({'?': None}).astype(float). \
applymap(lambda x: x if 1800 <= x <= 2021 else None)
print(df)
输出:
txt birth death
0 firstname lastname (1937-2015) 1937.0 2015.0
1 firstname lastname (1780-1820) NaN 1820.0
2 firstname lastname (1945-?) 1945.0 NaN
3 firstname lastname (1980-2022) 1980.0 NaN
使用 Series.str.extract
提取 Pandas 中第二年(从 1800 到 2099)的通用正则表达式解决方案,您可以利用
import pandas as pd
df = pd.DataFrame({'col':['firstname lastname (1937-2015)']})
yr = r'(?:1[89][0-9]{2}|20[01][0-9]|202[01])'
df['second_year'] = df['col'].str.extract(fr'(?s)(?<!\d){yr}(?!\d).*?({yr})(?!\d)')
# => df['second_year']
# 0 2015
# Name: second_year, dtype: object
参见regex demo。 详情:
(?s)
-.
现在跨行匹配(?<!\d)
- 左侧数字边界(?:1[89][0-9]{2}|20[01][0-9]|202[01])
- 从 1800 年到 2021 年(?!\d)
- 右手数字边界.*?
- 任何文本,尽可能少的字符(1[89][0-9]{2}|20[01][0-9]|202[01])
- 第 1 组(Series.str.extract
的实际 return 结果):1800 到 2021(?!\d)
- 右手数字边界
在这个具体案例中,一个简单的
df['second_year'] = df['col'].str.extract(r'.*-(\d{4})')
就足够了:任何文本(尽可能多的字符而不是换行符),然后是 -
和捕获到第 1 组的四位数字。
参见 this regex demo。
使用正则表达式查找从和到子短语的年份,然后拆分它并为第二年编制索引。您可以在数据框中使用它申请分配给列
txt="firstname lastname (1937-2015)"
pattern='(\d{4}\-\d{4})+'
matches=re.findall(pattern,txt)
print(matches[0].split('-')[1])
输出
2015