Stata中如何按字符串变量取值分组生成新分类变量
Stata字符串行业代码生成分组变量实现方案
原有代码失效原因
encode搭配inrange()的方案逻辑错误:encode的作用是将字符串按字典排序映射为从1开始的连续整数并附带值标签,不会解析字符串本身的数值含义。比如"10.112"和"9.999"两个字符串,按字典序"10.xxx"排在"9.xxx"前面,encode后前者对应的整数更小,和实际数值大小完全无关,因此用它做数值区间判断必然出错。- 循环写法的问题:一是没有提前生成目标变量,Stata中对不存在的变量执行
replace会直接报错;二是代码中混用BRANSCH、BRANSCH1变量名,很容易因变量名不匹配导致赋值失败;三是逐值循环效率偏低,这类匹配场景有更简洁的内置函数可用。
具体实现方案
根据分组逻辑选择对应方法即可:
场景1:指定离散代码精确匹配分组
适用于手动列出所有对应代码、按固定值分组的需求(比如你列出的14个食品行业代码归为1的场景)。
如果单组匹配值数量不多,可以直接用inlist()函数,代码可读性最高:
* 初始化新分类变量,默认赋值为缺失值 gen BRANSCH_NEW = . * 注意:字符串格式的inlist最多支持同时判断9个匹配值,超过数量拆分多个inlist用|(或逻辑)连接即可 replace BRANSCH_NEW = 1 if /// inlist(BRANSCH, "10.112", "10.120", "10.130", "10.390", "10.520", "10.710", "10.721", "10.822", "10.840") | /// inlist(BRANSCH, "10.850", "10.890", "11.020", "11.030", "12.000") * 其他分组按相同逻辑追加replace命令即可
如果单组匹配的代码数量很多,用local列表循环的方案更方便,不受参数数量限制:
gen BRANSCH_NEW = . * 定义分组1对应的所有代码,用空格分隔 local livsmedel "10.112 10.120 10.130 10.390 10.520 10.710 10.721 10.822 10.840 10.850 10.890 11.020 11.030 12.000" * 遍历列表逐值匹配赋值 foreach c of local livsmedel { replace BRANSCH_NEW = 1 if BRANSCH == "`c'" }
场景2:按行业代码数值区间分组
适用于你之前提到的“代码在1012区间归为1、1617.3区间归为2”这类按数值范围分组的需求。
不要用encode转码,先用destring把字符串格式的行业代码转为真正的数值型变量,再直接用inrange()做区间判断即可:
* 将字符串格式的BRANSCH转为数值型变量 destring BRANSCH, gen(bransch_num) * 初始化新分类变量 gen BRANSCH_NEW = . * 按数值区间赋值 replace BRANSCH_NEW = 1 if inrange(bransch_num, 10, 12) replace BRANSCH_NEW = 2 if inrange(bransch_num, 16, 17.3) replace BRANSCH_NEW = 3 if inrange(bransch_num, 19, 20.6) * 后续分组按相同逻辑追加replace命令即可
注意:执行
destring前可以先跑tab BRANSCH if missing(real(BRANSCH))检查是否存在非数字格式的异常代码,确认无异常后再执行转码,避免数据丢失。
进阶建议
如果分组规则复杂、需要频繁调整,可以单独维护一份两列的映射表:第一列为原始BRANSCH代码,第二列为对应的分组值,用merge命令将映射表和原数据匹配直接生成分组变量,后续调整规则只需要修改映射表,不需要改动核心处理代码。
内容的提问来源于stack exchange,提问作者Marika
相关产品推荐
相关产品推荐

