无预定义列类型时,如何识别数字编码的nominal变量?求Python/SAS方案
识别编码为数字的名义变量方法
Python 实现方案
1. 业务规则+关键词匹配法
针对常见的等级类名义变量(如满意度、评级),结合变量名关键词、取值范围和预定义编码映射识别:
- 提取变量名中的等级相关关键词(如
rating、level、grade、status、rank) - 检查变量的唯一取值是否为小范围离散整数(如1-3、1-5)
- 匹配预定义的等级编码映射(如
{1: 'Bad', 2: 'Good', 3: 'Better'})
代码示例:
import pandas as pd import re def is_nominal_encoded(df, col): # 检查变量名是否含等级关键词 keyword_pattern = re.compile(r'rating|level|grade|status|rank', re.IGNORECASE) if keyword_pattern.search(col): unique_vals = df[col].unique() # 检查取值是否为小范围离散整数 if all(isinstance(v, int) for v in unique_vals) and len(unique_vals) <= 5: return True # 匹配预定义等级映射(可根据业务扩展) grade_maps = [{1:'Bad',2:'Good',3:'Better'}, {1:'Low',2:'Medium',3:'High'}] col_vals = set(df[col].unique()) for mapping in grade_maps: if col_vals == set(mapping.keys()): return True return False # 测试用例 data = pd.DataFrame({ 'satisfaction_rating': [1,2,3,2,1,3], 'age': [25,30,35,40,45,50], 'product_level': [1,2,1,3,2,3] }) for col in data.columns: print(f"列 {col} 是否为编码的名义变量: {is_nominal_encoded(data, col)}")
2. 统计特征+互信息分析法
名义变量编码后数值间隔无实际意义,可通过统计特征区分:
- 计算变量与临时分类变量的互信息(互信息越高,越可能是名义变量)
- 对比熵值:名义变量熵值更接近分类变量,区间变量熵值随取值范围增大而升高
代码示例:
from sklearn.feature_selection import mutual_info_classif import numpy as np def check_nominal_via_stats(df, target_col): # 将已知区间变量分箱转为临时分类变量作为参考 temp_cat = pd.cut(df['age'], bins=3, labels=['young','mid','old']) # 计算目标变量与临时分类变量的互信息 mi = mutual_info_classif(df[[target_col]], temp_cat, discrete_features=True)[0] # 计算目标变量的熵 value_counts = df[target_col].value_counts(normalize=True) entropy = -np.sum(value_counts * np.log2(value_counts)) # 阈值可根据业务调整:互信息高+熵值适中(小基数) return mi > 0.1 and entropy < 2.0 # 测试用例 print(f"satisfaction_rating 统计特征判断: {check_nominal_via_stats(data, 'satisfaction_rating')}") print(f"age 统计特征判断: {check_nominal_via_stats(data, 'age')}")
3. 多维度规则引擎判断
综合基数、取值类型、业务关键词避免单一阈值问题:
- 基数≤10(可根据业务调整,远小于区间变量基数)
- 取值为非连续整数(无小数、无大跨度连续递增值)
- 变量名不含
amount、price、age等区间变量关键词
SAS 思路
1. PROC FREQ + 变量名规则检查
通过PROC FREQ查看频率分布,结合变量名关键词过滤:
/* 获取数据集内的数值型变量 */ proc sql; create table num_vars as select name from dictionary.columns where libname='WORK' and memname='DATA' and type='num'; quit; %macro check_nominal; %do i=1 %to &sqlobs; %let var=%scan(&name_list, &i); proc freq data=data; tables &var / nocum nocol; title "Frequency of &var"; run; /* 检查变量名是否含等级关键词 */ %if %sysfunc(indexw(%lowcase(&var), rating)) or %sysfunc(indexw(%lowcase(&var), level)) %then %do; %put &var is likely an encoded nominal variable; %end; %end; %mend; proc sql noprint; select name into :name_list separated by ' ' from num_vars; quit; %check_nominal;
2. DATA步逻辑判断
在DATA步中结合唯一值数量、取值范围编写判断逻辑:
data nominal_check; set data end=eof; array nums _numeric_; if _n_=1 then do; declare hash h(); h.defineKey('val'); h.defineDone(); end; do over nums; val = nums; h.add(); end; if eof then do; do over nums; var_name = vname(nums); unique_count = h.num_items; /* 判断规则:唯一值≤5且为整数 */ if unique_count <=5 and val=int(val) then do; is_nominal = 1; end; else is_nominal = 0; output; end; end; keep var_name is_nominal; run;
内容的提问来源于stack exchange,提问作者newtostack
相关产品推荐
相关产品推荐

