ARTICLE DETAIL

资讯详情

深耕网站SEO优化与搜索引擎排名提升的一线实战洞察。

Stata处理CFPS数据:从个人记录计算家庭人口数的三种方法

Stata处理CFPS数据:从个人记录计算家庭人口数的三种方法 1. 从“家庭”到“个人”CFPS数据结构与核心挑战如果你正在用Stata处理中国家庭追踪调查CFPS的数据并且想计算一个看似简单的指标——家庭人口数量那你可能已经发现事情并没有想象中那么直接。CFPS作为一项经典的追踪调查其数据结构设计得非常精细但也因此给初次接触的研究者带来了一些困惑。最核心的挑战在于CFPS的数据通常是以“个人”为观测单位的也就是说数据集的每一行对应的是一个被访者个人而不是一个家庭。我们无法像处理某些汇总数据那样直接找到一个名为“家庭人口数”的变量。那么我们如何从以个人为单位的数据中还原出以家庭为单位的统计量呢这背后涉及对CFPS数据结构、关键标识变量的深刻理解以及Stata中一些核心数据操作命令的灵活运用。这个过程不仅是完成一个简单的计数任务更是理解追踪调查数据、进行家庭层面分析的基础。无论是后续计算家庭人均收入、分析家庭消费结构还是研究家庭决策准确的家庭规模变量都是不可或缺的基石。接下来我将结合具体的Stata操作一步步拆解这个问题并分享一些在处理过程中容易踩坑的细节。2. 理解CFPS数据骨架pid, fid 与跨年匹配在动手写代码之前我们必须先搞清楚CFPS数据的“身份证系统”。这是所有操作的前提如果这里理解错了后面的结果全都会错。2.1 核心标识变量pid 与 fid在CFPS数据中有两个变量至关重要通常命名为pid和fid不同年份或模块的变量名可能略有差异如pid可能为pid_a_ffid可能为fid_a_f但逻辑一致。pid(个人ID): 这是每个受访者在整个CFPS调查中的唯一终身标识符。无论这个人在哪一年被访问也无论他/她属于哪个家庭这个ID是固定不变的。它是连接同一个人在不同年份数据的桥梁。fid(家庭ID): 这是每个家庭在特定调查年份的唯一标识符。这里有一个非常关键的细节CFPS的家庭ID (fid) 是会随时间变化的。当一个家庭发生分裂如子女结婚分家或合并时会生成新的家庭ID。因此fid只能用于在同一年份的数据内识别哪些个人属于同一个家庭。注意在开始分析前务必使用describe或codebook命令确认你当前使用的数据集中个人ID和家庭ID的确切变量名。例如codebook pid_a_f fid_a_f。2.2 数据结构的直观展示假设我们有一个2020年CFPS成人数据的简化片段它看起来是这样的以个人为观测单位pidfid_2020姓名与户主关系其他变量...100012001张三户主...100022001李四配偶...100032001张五子女...100042002王六户主...100052002赵七子女...从这个表格可以清晰地看到数据集有5行代表5个被访的个人。家庭ID (fid_2020) 为 2001 的家庭包含了 pid 为 10001, 10002, 10003 的三个人。家庭ID (fid_2020) 为 2002 的家庭包含了 pid 为 10004, 10005 的两个人。 我们的目标就是要生成一个新变量比如叫family_size_2020对于第一个家庭的所有成员这个变量的值都是3对于第二个家庭的所有成员这个变量的值都是2。2.3 跨年份分析的特别提醒如果你要做跨年份的追踪分析比如研究2020-2022年家庭规模的变化直接使用fid进行家庭匹配是错误的。因为2020年的家庭2001在2022年可能因为分家变成了家庭2001和家庭3001。正确的做法是使用个人ID (pid)先提取出每个年份下属于这些个人的家庭ID然后再基于每年的家庭ID分别计算当年的家庭规模。或者使用CFPS官方提供的跨年家庭匹配变量如fid_*的纵向匹配变量这需要仔细查阅CFPS的代码簿和用户手册。3. Stata实战三种方法计算家庭人口数理解了数据结构后我们就可以开始用Stata实现了。这里介绍三种常用的方法从基础到高效它们的结果在理论上应该是一致的。3.1 方法一使用bysort与egen组合最常用这是最直观、最Stata风格的方法。思路是先按照家庭ID分组然后在每个组内创建一个新的变量这个变量的值等于该组的观测值数量即家庭成员数。* 假设当前数据集为2020年数据家庭ID变量名为 fid20 * 第一步确保数据已按照家庭ID排序bysort会自动完成 bysort fid20: gen family_size _N * 第二步检查结果 list pid fid20 family_size in 1/10, sepby(fid20)bysort fid20:这是一个前缀命令。它告诉Stata其后面紧跟的命令这里是gen需要分别在每个fid20组内执行。fid20相同的所有观测行会形成一个组。_N:这是一个Stata内置的系统变量在bysort分组环境下它表示当前组内的观测值总数。对于fid202001这个组_N等于3对于fid202002这个组_N等于2。gen family_size _N:在每一个分组内生成一个新变量family_size并为组内每一行都赋值为该组的_N。这样属于同一个家庭的所有成员他们的family_size变量值就都是该家庭的总人数了。3.2 方法二使用collapse与merge分步操作这种方法分为两步首先将数据聚合到家庭层面计算人数然后再将结果合并回个人层面数据。这种方法在需要同时计算多个家庭层面统计量时特别有用。* 第一步保存原始个人数据 preserve * 第二步聚合collapse到家庭层面计算每个家庭的观测数即人数 collapse (count) member_count pid, by(fid20) * 解释以 fid20 分组统计每个组内 pid 的非缺失值数量生成新变量 member_count rename member_count family_size save “family_level_data.dta”, replace * 第三步恢复原始数据并合并家庭规模信息 restore merge m:1 fid20 using “family_level_data.dta” drop _mergecollapse:这是一个强大的聚合命令将数据从个人层面“压缩”到家庭层面。(count) member_count pid表示对pid进行计数计数时会自动忽略缺失值并将结果存储在名为member_count的新变量中。merge m:1:这是数据合并命令。m:1表示“多对一”合并即当前内存中的个人数据多条记录对应一个家庭去匹配刚刚保存的家庭层面数据一条记录对应一个家庭。通过fid20这个关键变量进行匹配。优点collapse命令可以一次性计算多个统计量例如同时计算家庭平均年龄、最高教育年限等collapse (count) sizepid (mean) avg_ageage (max) max_eduedu, by(fid20)。3.3 方法三使用egen的count()函数简洁直观egen命令提供了另一个简洁的函数来实现分组计数。egen family_size count(pid), by(fid20)egen ... count():egen是extended generate的缩写它提供了比gen更丰富的函数。count(pid)会计算pid的非缺失值数量。by(fid20):指定分组变量即在每个fid20的组内分别执行count()函数。这种方法非常简洁本质上和方法一逻辑相同。但在某些复杂的分组条件下egen的count()函数可能比bysort更灵活。实操心得对于单纯的计数我最推荐方法一bysort: gen var _N。它运行速度通常最快代码最简洁且是Stata用户最惯用的语法便于交流和复查。方法二更适合需要一次性生成多个家庭层面指标的场景。你可以三种方法都试一下用assert命令验证结果是否一致assert family_size_method1 family_size_method2。4. 关键细节与进阶问题处理计算家庭规模远不止运行一行命令那么简单。在实际研究中以下几个细节直接关系到结果的准确性。4.1 处理缺失值与特殊成员CFPS数据中可能存在个人ID (pid) 缺失的情况或者你需要排除某些特定身份的成员如已去世但仍在家庭档案中的人。原始的_N或count()会计算组内所有行。如果基于pid计数count(pid)会自动忽略pid为缺失值的行这是安全的。如果需要排除特定人群例如只计算在世家庭成员。你需要先定义一个条件标识。* 假设有一个变量 “alive” 表示是否在世1在世0去世 gen alive_member (alive 1) // 生成一个在世成员的指示变量 bysort fid20: egen family_size_alive total(alive_member) * 或者使用条件计数 bysort fid20: gen count_alive sum(alive 1) bysort fid20: replace count_alive count_alive[_N] // 取每组最后一个累计值这里egen的total()函数会对组内alive_member的值进行求和由于该变量在世为1不在世为0求和结果就是在世人数。4.2 区分“家庭户”与“集体户”CFPS样本包含普通家庭户和集体户如学校宿舍、养老院。计算家庭规模时通常只关注家庭户。集体户的“家庭”概念不同其“家庭规模”可能没有实际意义。操作在计算前先检查数据中是否有户类型变量如hhtype。通常可以先筛选出家庭户再进行计算。preserve keep if hhtype 1 // 假设1代表家庭户 bysort fid20: gen family_size_hh _N save “family_hh_data.dta”, replace restore4.3 跨年份追踪与家庭动态这是CFPS分析中的高级话题。如前所述家庭ID (fid) 会随时间变化。场景你想计算每个家庭2020年和2022年的规模并查看变化。错误做法直接合并两年数据用fid匹配。因为2022年的新家庭在2020年数据中不存在。正确做法之一基于个人追踪分别计算2020年和2022年每个fid的家庭规模生成两个数据集size2020.dta(包含fid20,size20) 和size2022.dta(包含fid22,size22)。使用2020年的个人数据提取每个人在2020年的fid20和2022年的fid22这需要有一个包含pid,fid20,fid22的纵向匹配文件。将size2020.dta通过fid20合并到这个纵向匹配文件再将size2022.dta通过fid22合并进来。这样每个pid就同时有了其2020年所在家庭的规模和2022年所在家庭的规模。你可以进一步分析那些pid所属家庭规模的变化。4.4 结果验证与常识判断生成变量后一定要做基本验证。描述性统计summarize family_size, detail。查看均值、中位数、最小值和最大值。家庭规模最小值不应小于1除非你排除了所有成员最大值也会在一个合理范围内例如中国家庭通常不超过10余人。如果出现规模为0或异常大如100说明分组可能出错。列表检查list pid fid20 family_size if family_size 1。查看所有规模为1的家庭确认是否是真正的单人户。交叉比对利用CFPS数据库中已有的、可能反映家庭规模的变量进行交叉验证例如家庭问卷中可能直接有“本户共有人口数”这样的问题虽然它可能与基于个人问卷汇总的结果因定义不同而有细微差异但大体上应保持一致。5. 从家庭规模到衍生变量构建计算出准确的家庭规模 (family_size) 后它就成为了一个强大的基础变量可以支撑许多重要的衍生分析。5.1 计算家庭人均变量这是最直接的应用。例如计算家庭人均纯收入、人均消费支出、人均住房面积等。* 假设 total_income 是家庭总收入变量可能来自家庭问卷或由个人收入加总得到 gen income_per_capita total_income / family_size注意这里隐含一个关键步骤——家庭层面变量的获取。total_income这类变量通常存储在家庭问卷数据集中。你需要先通过fid和年份将家庭问卷中的总收入变量合并到个人数据中然后再进行人均计算。合并命令类似于merge m:1 fid20 using “household_questionnaire_2020.dta”。5.2 生成家庭类型变量根据家庭规模、代际结构等可以生成分类的家庭类型变量用于亚组分析。* 生成家庭规模分类 gen size_cat . replace size_cat 1 if family_size 1 // 单人户 replace size_cat 2 if family_size 2 // 二人户 replace size_cat 3 if family_size 3 family_size 4 // 三至四人户 replace size_cat 4 if family_size 5 // 五人及以上户 label define size_cat_lb 1 “单人户” 2 “二人户” 3 “三至四人户” 4 “五人及以上户” label values size_cat size_cat_lb * 结合年龄和关系粗略判断是否为核心家庭仅夫妻与未婚子女 * 假设有变量 relation (与户主关系) age bysort fid20: egen has_parent max(relation 1) // 假设1为户主判断是否有户主 bysort fid20: egen has_spouse max(relation 2) // 假设2为配偶 bysort fid20: egen has_child max(relation 3) // 假设3为子女 gen is_nuclear (has_parent 1 has_spouse 1 has_child 1 family_size 4)这个is_nuclear变量可以用于后续的亚组分析比较核心家庭与非核心家庭在某些指标上的差异。5.3 在回归模型中作为控制变量或交互项家庭规模是社会科学研究中一个经典的控制变量几乎在分析任何家庭产出如教育投资、健康、消费等时都需要考虑。regress children_edu investment family_size parent_edu, robust你也可以研究家庭规模的调节效应gen investment_x_size investment * family_size regress children_edu investment family_size investment_x_size parent_edu, robust如果investment_x_size的系数显著说明家庭投资对子女教育的影响会因家庭规模的不同而不同。6. 常见错误排查与调试指南即使理解了原理和命令在实际操作中仍可能遇到问题。下面是一些常见错误的排查思路。6.1 结果全是1或异常值症状运行bysort fid: gen size _N后summarize size发现所有值都是1或者数值巨大。诊断这几乎肯定是因为分组变量fid在每个观测值上都是唯一的也就是说Stata认为每一行都是一个独立的“组”。排查检查变量名tab fid或codebook fid。看看fid有多少个不同的值如果不同值的数量等于数据集观测值总数 (_N)那就错了。很可能你错误地使用了个人ID (pid) 或者一个不相关的变量。检查数据类型describe fid。确保fid是数值型int,long,float,double。有时从文本文件导入家庭ID可能被误读为字符串str#这会导致排序和分组出现问题。用destring fid, replace转换。检查缺失值misstable summarize fid。如果fid有大量缺失那么缺失值会被视为同一个组导致一些家庭被错误合并。需要根据数据说明处理缺失值。6.2 合并merge后家庭规模变量缺失症状使用方法二collapsemerge后family_size变量有很多缺失值。诊断合并失败很多个人记录没有匹配到对应的家庭汇总信息。排查检查_merge变量在drop _merge之前先tab _merge。它会告诉你匹配结果_merge1表示主数据个人数据有但用数据家庭汇总数据无_merge2相反_merge3表示匹配成功。如果大量是1说明用于合并的fid在两个数据集中不一致可能是变量名不同、年份不同、或数据子集不同。核对关键变量确保用于合并的变量在两个数据集中名称完全相同、数据类型相同、含义相同。比较summarize fid在两个数据集中的结果。确认数据范围你用于collapse的数据集是否和你想要合并回去的个人数据集是同一个样本子集比如个人数据可能删除了某些缺失值而collapse用的是全样本。6.3 计算的人均变量出现极端值症状income_per_capita出现极大或极小的值。诊断分子总收入或分母家庭规模可能存在问题。排查检查分母summarize family_size if family_size 0。家庭规模不应小于等于0。如果出现回到第6.1步检查家庭规模计算。检查分子summarize total_income。查看收入是否有负值、零值或异常大的值可能是单位错误如“元”与“万元”混淆。检查关系scatter income_per_capita family_size画个散点图。看是否存在明显的异常点。用list pid fid total_income family_size income_per_capita if income_per_capita 1000000 | income_per_capita 100列出极端值观察。处理极端值根据研究惯例可以对人均收入进行缩尾处理winsor2 income_per_capita, cuts(1 99) replace或直接剔除极端异常值。6.4 跨年分析时家庭无法对应症状想比较同一家庭两年间的规模变化但匹配率极低。诊断直接使用了错误的ID进行匹配。解决放弃直接使用fid匹配。必须使用CFPS官方提供的纵向链接文件。这个文件通常包含了个人在不同年份对应的家庭ID。你的分析链路应该是个人PID - 纵向链接文件找到其各年FID - 各年家庭规模数据通过各年FID获取 - 合并到个人层面。这个过程需要仔细阅读CFPS的用户手册和代码簿找到正确的链接变量。
返回列表