Pandas如何识别object列混合值类型(含日期)并拆分子DataFrame
问题场景
我们首先构造了仅包含1列字符串值的DataFrame,列内字符串实际对应整数、浮点数、布尔值、日期等多种数据类型,即不同类型的值全部以字符串格式编码存储,构造代码如下:
import pandas as pd mixed_values = {'col1': ["123", "3.14", "1010-10-01T01:01:01", "Say Hello'Hello !", "True" ]} df = pd.DataFrame(data=mixed_values) df # 输出结果: col1 0 123 1 3.14 2 1010-10-01T01:01:01 3 Say Hello'Hello ! 4 True df.dtypes # 输出结果: col1 object dtype: object
核心需求
- 如何按照object列内值的实际类型(整数、浮点数、日期、字符串、布尔值)拆分,得到对应的子DataFrame?
预期拆分后得到如下分类子DataFrame:
df_int # 预期输出: col1 0 123 df_float # 预期输出: col1 1 3.14 df_date # 预期输出: col1 2 1010-10-01T01:01:01 df_string # 预期输出: col1 3 Say Hello'Hello ! df_boolean # 预期输出: col1 4 True
现有方案尝试
参考字符串值类型检测、ast.literal_eval处理DataFrame的实现思路,我们编写了类型识别函数,为object列新增值类型标注列,实现代码如下:
import ast, re def gives_data_type_inside_string(val): if len(val) == 0: return '' try: t=ast.literal_eval(val) except ValueError: return 'STRING' except SyntaxError: return 'STRING' else: if type(t) in [int, float, bool]: if t in set((True,False)): return 'BOOLEAN' if type(t) is int: return 'INT' if type(t) is float: return 'FLOAT' else: return 'STRING' def add_col_literal_return(input_df, col_in, col_out): # 避免修改原始DataFrame input_df_copy = input_df.copy() input_df_copy[f"{col_out}"] = input_df_copy[f"{col_in}"].apply(lambda x: gives_data_type_inside_string(x)) return input_df_copy # 对DataFrame应用类型标注函数 df = df.pipe(add_col_literal_return, "col1", "value_type") # 输出带类型标注的DataFrame: col1 value_type 0 123 INT 1 3.14 FLOAT 2 1010-10-01T01:01:01 STRING 3 Say Hello'Hello ! STRING 4 True BOOLEAN
完成类型标注后,通过类型筛选即可得到对应子DataFrame,筛选代码如下:
df_int= df.query('value_type == "INT"') df_float= df.query('value_type == "FLOAT"') df_string= df.query('value_type == "STRING"') df_boolean= df.query('value_type == "BOOLEAN"') print(df_int) # 输出: col1 value_type 0 123 INT print(df_float) #输出 col1 value_type 1 3.14 FLOAT print(df_string) # 输出: col1 value_type 2 1010-10-01T01:01:01 STRING 3 Say Hello'Hello ! STRING print(df_boolean) # 输出: col1 value_type 4 True BOOLEAN
现有方案可以实现整数、浮点数、布尔值、字符串类型的识别与子DataFrame拆分,但无法识别日期类型,ISO格式的日期字符串会被误判为普通字符串。
待解决问题
- Pandas中是否存在更优方案,识别object dtype列内值的实际类型,并按类型提取对应子DataFrame?
- 现有方案需要补充什么逻辑,才能实现日期类型检测,提取日期类型对应的子数据集?
实现方案
要补全日期识别能力,只需要在类型判断逻辑中优先加入日期校验即可:在走ast.literal_eval判断之前,先尝试用pd.to_datetime对字符串做日期解析,设置errors='coerce',如果解析结果不是空值(即不是NaT),就判定为日期类型。
注意:日期判断要放在最前面,避免部分符合数字格式的日期(比如纯数字时间戳)被误判为整数/浮点数。
修正后的类型识别函数代码如下:
import ast import pandas as pd from pandas import NaT def gives_data_type_inside_string(val): if len(val) == 0: return '' # 优先判断日期类型 try: date_parse_res = pd.to_datetime(val, errors='coerce') if date_parse_res is not NaT: return 'DATE' except: pass # 原有ast类型判断逻辑 try: t=ast.literal_eval(val) except ValueError: return 'STRING' except SyntaxError: return 'STRING' else: if type(t) in [int, float, bool]: if t in set((True,False)): return 'BOOLEAN' if type(t) is int: return 'INT' if type(t) is float: return 'FLOAT' else: return 'STRING'
重新应用类型标注函数后,即可正确识别日期类型,筛选得到df_date子数据集:
df = df.pipe(add_col_literal_return, "col1", "value_type") df_date = df.query('value_type == "DATE"') print(df_date) # 输出: col1 value_type 2 1010-10-01T01:01:01 DATE
如果需要适配更多自定义日期格式,可以在日期判断环节加入正则预校验,先匹配符合业务日期格式的字符串再做解析,进一步降低误判概率。
内容的提问来源于stack exchange,提问作者an ch
相关产品推荐
相关产品推荐

