为何使用dplyr的mutate与recode重编码数据后未完全生效?
问题分析与解决方法
你遇到的核心问题是浮点数精度导致的匹配失败:你在recode里用字符串形式的浮点数(比如"30.43478")去匹配数值型的HSE列,但实际数据中这些浮点数的存储精度可能和你写的字符串不一致(比如原始数据里是30.4347826087,而非你写的30.43478),导致部分值匹配不上,看起来没被重编码。
解决方法
方法1:用case_when按数值范围匹配(推荐)
这种方法不受浮点数精度影响,逻辑更清晰:
psqi_data <- psqi_data %>% dplyr::mutate(HSE = dplyr::case_when( HSE %in% c(30.43478, 31.57895) ~ 3, HSE %in% c(66.66667, 67.92453, 68.96552, 70.00000, 70.58824) ~ 2, HSE %in% c(75.00000, 76.47059, 76.74419, 76.92308, 77.41935) ~ 1, HSE %in% c(109.09091, 114.28571, 120.00000, 150.00000) ~ 0, TRUE ~ HSE # 保留未匹配的原始值,可选 ))
如果担心数值精度,还可以用dplyr::near()函数判断近似相等:
psqi_data <- psqi_data %>% dplyr::mutate(HSE = dplyr::case_when( near(HSE, 30.43478) | near(HSE, 31.57895) ~ 3, near(HSE, 66.66667) | near(HSE, 67.92453) | near(HSE, 68.96552) | near(HSE, 70.00000) | near(HSE, 70.58824) ~ 2, near(HSE, 75.00000) | near(HSE, 76.47059) | near(HSE, 76.74419) | near(HSE, 76.92308) | near(HSE, 77.41935) ~ 1, near(HSE, 109.09091) | near(HSE, 114.28571) | near(HSE, 120.00000) | near(HSE, 150.00000) ~ 0, TRUE ~ HSE ))
方法2:统一浮点数精度后再用recode
先把HSE列四舍五入到指定小数位,再进行匹配:
# 先统一精度到6位小数 psqi_data <- psqi_data %>% dplyr::mutate(HSE_rounded = round(HSE, 6), HSE = dplyr::recode(HSE_rounded, 30.43478 = 3, 31.57895 = 3, 66.66667 = 2, 67.92453 = 2, 68.96552 = 2, 70.00000 = 2, 70.58824 = 2, 75.00000 = 1, 76.47059 = 1, 76.74419 = 1, 76.92308 = 1, 77.41935 = 1, 109.09091 = 0, 114.28571 = 0, 120.00000 = 0, 150.00000 = 0)) %>% dplyr::select(-HSE_rounded) # 删掉临时列
失效原因
当HSE是数值型时,直接用字符串(比如"30.43478")匹配,只有数据中的值和字符串完全一致(包括精度)时才会生效。但浮点数在计算机中存储时可能存在微小误差,比如30.43478实际存储为30.434780000000002,这时候字符串"30.43478"就匹配不上了。
内容的提问来源于stack exchange,提问作者Ella
相关产品推荐
相关产品推荐

