如何在R中为有序数据的黑人观测值匹配对应排名的白人索引值
在R中复现Rank and Replace方法的第4步
我正在R中复现某论文的rank and replace方法,卡在了第4步:为黑人观测值匹配最近的后续白人观测值的原始索引值,填补index_new中的NA。数据集已按rank_weighted排序,black/white为二分变量(1代表对应种族),目前已完成部分匹配(仅匹配了前一个观测值是白人的黑人样本),但连续黑人样本的index_new仍为NA,需要自动找到后续最近的白人样本的index_orig来替换。
现有样本数据:
data <- structure(list(black = structure(c(0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0 ), format.stata = "%9.0g"), white = structure(c(1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1), format.stata = "%9.0g"), rank_weighted = c(0.264, 0.278, 0.46, 0.656, 0.743, 0.813, 0.858, 1.124, 1.41, 1.416, 1.608, 1.762, 1.962, 2.008, 2.128, 2.506, 2.513, 2.737, 2.967, 3.158, 3.339, 3.682, 3.999, 4.057, 4.149, 4.274, 4.406, 4.481, 4.558, 4.872), index_orig = structure(c(-5.718, -5.502, -5.659, -5.636, -5.634, -5.502, -5.598, -5.584, -5.502, -5.572, -5.549, -5.544, -5.544, -5.502, -5.535, -5.484, -5.533, -5.527, -5.515, -5.453, -5.51, -5.502, -5.502, -5.426, -5.502, -5.502, -5.502, -5.409, -5.502, -5.502), format.stata = "%10.0g"), index_new = c(NA, -5.718, NA, NA, NA, -5.634, NA, NA, NA, -5.502, NA, NA, NA, -5.544, NA, -5.535, NA, NA, NA, NA, NA, NA, NA, -5.502, NA, NA, NA, -5.502, NA, NA)), row.names = c(NA, -30L), class = c("tbl_df", "tbl", "data.frame"))
之前尝试的R循环未生效,原Stata循环逻辑是:从当前行向后找第i个观测值,如果是白人且当前index_new为NA,就替换成该白人的index_orig,直到i达到15。
解决方案1:向量化方法(高效适配大数据)
无需循环,通过标记+向后填充实现:
library(dplyr) library(tidyr) data_processed <- data %>% # 仅保留白人的index_orig,其余设为NA mutate(temp_index = ifelse(white == 1, index_orig, NA)) %>% # 从后向前填充(即给每个黑人匹配后续最近的白人索引) fill(temp_index, .direction = "up") %>% # 填补黑人样本的NA值,保留已匹配的结果 mutate(index_new = ifelse(black == 1 & is.na(index_new), temp_index, index_new)) %>% # 删除临时列 select(-temp_index)
解决方案2:复现Stata的while循环逻辑
原循环失效是因为逻辑判断错误(is.na(data$index_new == T)应为is.na(data$index_new)),修正后的代码:
val <- 1 while (val <= 15) { data$index_new <- ifelse( # 条件:黑人样本、index_new为NA、向后第val个观测值是白人 data$black == 1 & is.na(data$index_new) & lead(data$white, n = val, default = 0) == 1, lead(data$index_orig, n = val), data$index_new ) val <- val + 1 }
- 添加
default = 0避免超出数据集范围时返回NA,导致条件不成立; - 从
val=1开始可覆盖你之前用lag完成的匹配,也可保留原ifelse后从val=2开始。
验证结果
处理后,第3行的index_new会被替换为第4行的-5.636,第7、8行替换为第9行的-5.502,符合预期。
内容的提问来源于stack exchange,提问作者eliseabril
相关产品推荐
相关产品推荐

