如何用Python解析pandas数据框中极度模糊的艺术创作日期?
太懂你这种对着一堆格式乱七八糟的艺术品日期挠头的感觉了!自己写Transformer类啃了好几天,确实不如直接用现成工具香——Python生态里有几个专门对付这种模糊、非标准化日期的库,刚好适配你遇到的所有场景,给你梳理一下:
可用的Python工具推荐
1. dateparser - 处理多格式模糊日期的首选
这个库对非标准日期的兼容性拉满,能自动识别circa/c./ca.这类模糊前缀,世纪表述、年代范围、多日期分隔(分号/逗号)甚至BCE/CE纪年都不在话下。
给你整个适配你场景的示例:
import dateparser import pandas as pd # 你的日期样本 date_samples = [ "1998", "circa 1995", "c. 2003-5", "March 2, 1904", "1st quarter of 19th century", "19th to 20th century", "ca. late 19th and early 20th Century BCE", "500", "206 BCE-240 CE", "1995-99", "designed 1950, produced 1969", "designed 1935, produced circa 1946-1968", "1990; and 1989", "1975/97", "no date", "n.d.", "mid 1900s", "late 1940's" ] def parse_art_date(date_str): # 处理无日期的情况 if date_str.lower() in ["no date", "n.d."]: return None # 针对designed/produced这类多时间节点的情况,提取并解析每个日期 if "designed" in date_str or "produced" in date_str: # 拆分出每个时间节点的日期部分 date_parts = [] for segment in date_str.split(','): if any(kw in segment for kw in ["designed", "produced"]): # 提取日期字符串(比如"designed 1950"里的"1950") date_text = ' '.join(segment.split()[1:]) date_parts.append(dateparser.parse(date_text)) return tuple(date_parts) # 处理普通模糊日期 return dateparser.parse(date_str) # 应用到DataFrame df = pd.DataFrame({"creation_date": date_samples}) df["parsed_dates"] = df["creation_date"].apply(parse_art_date)
2. parsedatetime - 专攻自然语言风格日期
这个库对“1st quarter of 19th century”“mid 1900s”“late 1940's”这类自然语言化的日期描述解析更精准,会返回结构化的datetime对象,适合侧重语义的场景。
示例代码:
import parsedatetime as pdt cal = pdt.Calendar() def parse_natural_date(date_str): if date_str.lower() in ["no date", "n.d."]: return None # 尝试自然语言解析 result, status = cal.parseDT(date_str) if status == 1: # 解析成功 return result # 解析失败就fallback到dateparser return dateparser.parse(date_str)
3. 正则+日期库组合 - 搞定极端特殊格式
如果上面的库对“1937-42/48”“1975/97”这类奇葩格式处理不够精准,你可以先用正则提取核心日期片段,再交给日期库解析:
import re import dateparser def parse_special_dates(date_str): # 处理范围日期(比如1995-99、206 BCE-240 CE) range_match = re.match(r"(\d+.*?)-(\d+.*)", date_str) if range_match: start = dateparser.parse(range_match.group(1)) end = dateparser.parse(range_match.group(2)) return (start, end) # 处理斜杠分隔的日期(比如1975/97 -> 1975、1997) slash_match = re.match(r"(\d{4})/(\d{2})", date_str) if slash_match: year1 = slash_match.group(1) year2 = f"{year1[:2]}{slash_match.group(2)}" return (dateparser.parse(year1), dateparser.parse(year2)) # 其他情况交给dateparser return dateparser.parse(date_str)
4. 历史日期(BCE/CE)的精准处理
dateparser已经支持BCE/CE解析,但如果需要更严谨的历史年代转换,可以用arrow库,它对公元前/公元后日期的处理更专业:
import arrow def parse_historical_date(date_str): try: return arrow.get(date_str).datetime except: # 解析失败fallback return dateparser.parse(date_str)
额外实用建议
- 对于包含多个时间节点的字符串(比如designed/produced),可以考虑把解析结果拆成单独的列(
design_date、production_date),方便后续分析。 - 无日期条目(no date/n.d.)统一标记为
None,避免干扰后续数据统计。 - 可以把这些解析函数做成一个流水线:先试parsedatetime,失败用dateparser,最后用正则兜底,最大化覆盖所有场景。
内容的提问来源于stack exchange,提问作者Austin
相关产品推荐
相关产品推荐

