如何更Pythonic地识别Pandas DataFrame中的Decimal与字符串列
区分DataFrame中显示为object的Decimal与字符串列
首先得说,你遇到的这个情况确实挺常见——Pandas里把Decimal和字符串都归到object dtype里,直接用df.dtypes根本分不出来。你的当前解法是取第一行元素的类型来筛选,思路没问题,但确实有更简洁、更健壮的Pythonic写法。
先回顾下你的场景代码:
import pandas as pd import decimal data = {'dec1': [1.1, 1.2],'str1': ["a","b"]} df = pd.DataFrame(data) df.dec1 = df.dec1.apply(lambda x: decimal.Decimal(x)) print(df.dtypes) # 输出全是object,完全没法区分
你的现有代码:
actual_col_types = df.iloc[0].apply(type) df_decimals = df.loc[:,actual_col_types==decimal.Decimal]
这个写法的隐患是:如果某列第一行是None(或者其他非Decimal/字符串的特殊值),判断就直接错了,而且也没考虑列里存在混合值的情况。
推荐的Pythonic实现
这里有几种不同场景下的优化写法,你可以按需选:
1. 严格检查:整列所有元素都是Decimal/字符串
如果你的列里没有空值,且类型统一,直接用all()结合isinstance来检查整列:
# 筛选所有元素都是Decimal的列 decimal_cols = df.columns[df.apply(lambda col: all(isinstance(val, decimal.Decimal) for val in col))] # 筛选所有元素都是字符串的列 str_cols = df.columns[df.apply(lambda col: all(isinstance(val, str) for val in col))] # 生成对应的子DataFrame df_decimals = df[decimal_cols] df_strings = df[str_cols]
用isinstance而不是直接比type是Python里的最佳实践——它支持继承关系(虽然Decimal没子类,但规范写法总是没错的)。
2. 宽松检查:列中存在至少一个Decimal/字符串
如果列里可能有None这类空值,或者允许少量混合值(比如大部分是Decimal,个别空值),就用any()来判断:
decimal_cols = df.columns[df.apply(lambda col: any(isinstance(val, decimal.Decimal) for val in col))] str_cols = df.columns[df.apply(lambda col: any(isinstance(val, str) for val in col))]
3. 高效检查:处理大型DataFrame
如果你的DataFrame数据量很大,遍历整列所有元素效率太低,可以改成取第一个非空元素来判断类型——毕竟正常情况下列的类型是统一的:
def is_decimal_column(col): # 先过滤空值,取第一个有效元素判断 non_null_vals = col.dropna() if non_null_vals.empty: return False return isinstance(non_null_vals.iloc[0], decimal.Decimal) def is_string_column(col): non_null_vals = col.dropna() if non_null_vals.empty: return False return isinstance(non_null_vals.iloc[0], str) decimal_cols = df.columns[df.apply(is_decimal_column)] str_cols = df.columns[df.apply(is_string_column)]
这种写法速度快很多,同时也避免了空值带来的误判。
为啥说这些更Pythonic?
- 可读性更强:通过函数/匿名函数明确表达“检查列类型”的意图
- 健壮性更好:考虑了空值、混合值的边界情况
- 符合Python规范:用
isinstance做类型检查,而不是直接对比type对象
内容的提问来源于stack exchange,提问作者Julien Massardier
相关产品推荐
相关产品推荐

