在Python3中将出生日期数据框拆分为3个不同的列
有一个包含3种不同类型出生日期的数据框:在Python3中将出生日期数据框拆分为3个不同的列,python,regex,python-3.x,pandas,Python,Regex,Python 3.x,Pandas,有一个包含3种不同类型出生日期的数据框: df_dob=pd.DataFrame( [ {'date':'DOB 19 Jun 1951'}, {'date':'DOB Jun 1951'}, {'date':'DOB 1951'} ] ) 我正试图编写一个像上面这样的函数,以便将上面的数据帧转换为 3列: 第一栏可以容纳1951-06-19 00:00:00 第二栏可以容纳1951-06年 第三纵队可以容纳1951人 期望输出: df_dob['date'].apply(transform_
df_dob=pd.DataFrame(
[
{'date':'DOB 19 Jun 1951'},
{'date':'DOB Jun 1951'},
{'date':'DOB 1951'}
]
)
我正试图编写一个像上面这样的函数,以便将上面的数据帧转换为
3列:
第一栏可以容纳1951-06-19 00:00:00
第二栏可以容纳1951-06年
第三纵队可以容纳1951人
期望输出:
df_dob['date'].apply(transform_date)
以下是我的代码,有两个问题:
(1) 正则表达式无法处理“DOB Jun 1951”,因此返回“TypeError:type'NoneType'的对象没有len()
如本文所述:
(2) 如果我们从输入中删除“DOB Jun 1951”,我们将得到以下错误
57 df_dob[“日期”]。应用(转换日期)
“TypeError:无效的类型升级”
不知是否有更好的解决办法?谢谢
1951-06-19 00:00:00, NaN, NaN
NaN,1951-06,NaN
NaN,NaN,1951
重新导入
从datetime导入datetime,timedelta
def转换_日期(x):
如果len(x.split(“;”)>0:
regex=r“\bDOB((?:(?:3[01]|[12][0-9]|[0-9])[A-Za-z]+)?\d{4})\b”
#“DOB(.*)”
l=len(关于findall(regex,x.split(';')[0]))
如果l>0:
#new=re.findall('DOB(.*),x.split(';')[0])[0]
#而我认为你可以提取日期并跳过日期:
import re
from datetime import datetime, timedelta
def transform_date(x):
if len(x.split(';')) > 0:
regex = r"\bDOB ((?:(?:3[01]|[12][0-9]|0?[1-9]) [A-Za-z]+ )?\d{4})\b"
#'DOB (.*)'
l = len(re.findall(regex, x.split(';')[0]))
if l > 0:
# new = re.findall('DOB (.*)', x.split(';')[0])[0]
# while l <= len(re.findall('DOB (.*)', x.split(';')[0])):
new = re.findall(regex, x.split(';')[0])[l - 1]
print(new)
# print(type(new))
# l = l+1
if len(new) == 11:
print(datetime.strptime(new, '%d %b %Y'))
return pd.Series([datetime.strptime(new, '%d %b %Y'), np.nan, np.nan])
elif len(new) == 4:
print(datetime.strptime(new, '%Y').year)
return pd.Series([np.nan, np.nan, datetime.strptime(new, '%Y').year])
else:
print(str(datetime.strptime(new, '%b %Y').year)) + '-' + str(datetime.strptime(new, '%b %Y').month)
mmyyyy=str(datetime.strptime(new, '%b %Y').year) + '-' + str(datetime.strptime(new, '%b %Y').month)
return pd.Series([np.nan, mmyyyy, np.nan])
pattern=r“(?P\d{2}\s[A-Za-z]{3}\s\d{4})|(?P[A-Za-z]{3}\s\d{4})|(?P\d{4})”
dates=df[“date”].str[3:][.str.extract(模式)
日期[[“date1”,“date2”]=日期[[“date1”,“date2”]]。适用(pd.to_datetime)
打印(日期)
日期1日期2日期3
0 1951-06-19纳南
1 NaT 1951-06-01南
2 NaT NaT 1951年
再次感谢您@叶亨利!如果我想保留原始日期栏,我该怎么做dates=pd.concat(df[“date”],df[“date”].str[3:][.str.extract(pattern))
返回TypeError:第一个参数必须是pandas对象的iterable,您传递了一个类型为“Series”的对象
我想我已经搞定了df[[“date1”,“date2”,“date3”]=df[“date”].str[3:].str.extract(pattern,expand=True),
Hi@Henry Yik:我刚刚发现日期列不是很干净。可能有“1951年6月19日DOB;埃及POB Giza;护照1084010(埃及);替代护照19820215;圣战组织的作战和军事领导人。”在您的解决方案中,我发现模式也与护照匹配,如ort 19820215
。想知道是否有任何方法可以避免在这里提取passort,而只提取DOB后面的字符串?谢谢您可以使用str.split
首先按“;”进行拆分df[“date”].str.split(;”).str[0]
应该为您提供第一个元素@Chubaka。
pattern = r"(?P<date1>\d{2}\s[A-Za-z]{3}\s\d{4})|(?P<date2>[A-Za-z]{3}\s\d{4})|(?P<date3>\d{4})"
dates = df["date"].str[3:].str.extract(pattern)
dates[["date1","date2"]] = dates[["date1","date2"]].apply(pd.to_datetime)
print (dates)
date1 date2 date3
0 1951-06-19 NaT NaN
1 NaT 1951-06-01 NaN
2 NaT NaT 1951