conv_unit()函数在ifelse()语句中无法正常运行的问题排查
问题:度分十进制转十进制度时
ifelse()调用conv_unit()报错且结果异常 需求
需要将表格中混合存在的两种地理坐标格式(十进制度dec_deg、度分十进制deg_dec_min)统一转换为十进制度,使用dplyr::mutate()结合ifelse()调用measurements::conv_unit()时出现警告,且转换结果不符合预期。
可复现代码
library(dplyr) library(measurements) data_latlon <- tibble(latitude = c(8.726088, -16.365242, -19.888074, '1 40.232', '0 2.308', '2 2.356'), longitude = c(-83.180764, -62.015502, -40.549983, '75 54.301', '70 56.693', '72 41.143'), unit = c('dec_deg', 'dec_deg', 'dec_deg', 'deg_dec_min', 'deg_dec_min','deg_dec_min'))
场景1:全局使用ifelse()的问题
执行以下代码后出现警告,且latitude列转换结果错误:
data_latlon %>% mutate(latitude = ifelse(unit=='deg_dec_min', conv_unit(latitude, from = 'deg_dec_min', to = 'dec_deg'), latitude))
输出结果:
# A tibble: 6 × 3 latitude longitude unit <chr> <chr> <chr> 1 8.726088 -83.180764 dec_deg 2 -16.365242 -62.015502 dec_deg 3 -19.888074 -40.549983 dec_deg 4 2.34133333333333 75 54.301 deg_dec_min 5 2.356 70 56.693 deg_dec_min 6 0 72 41.143 deg_dec_min
警告信息:
Warning messages: 1: Problem while computing `latitude = ifelse(...)`. ℹ longer object length is not a multiple of shorter object length 2: Problem while computing `latitude = ifelse(...)`. ℹ data length is not a multiple of split variable
场景2:单独过滤后处理正常
仅筛选unit='deg_dec_min'的行时,转换结果正确:
data_latlon %>% filter(unit=='deg_dec_min') %>% mutate(latitude = ifelse(unit=='deg_dec_min', conv_unit(latitude, from = 'deg_dec_min', to = 'dec_deg'), latitude))
输出结果:
# A tibble: 3 × 3 latitude longitude unit <chr> <chr> <chr> 1 1.67053333333333 75 54.301 deg_dec_min 2 0.0384666666666667 70 56.693 deg_dec_min 3 2.03926666666667 72 41.143 deg_dec_min
问题原因
ifelse()会将整个latitude向量传入conv_unit(),而该列同时包含十进制度的字符型数值(如"8.726088")和度分十进制格式的字符串(如"1 40.232")。conv_unit()无法正确解析十进制度格式的字符串,导致处理后的结果向量长度与原向量不匹配,进而触发警告并返回错误的转换值。
解决方案
可以通过逐行处理或严格的条件分支匹配来解决,以下是两种可行方法:
方法1:使用rowwise()逐行处理
rowwise()会让mutate()对每一行单独执行计算,确保conv_unit()只接收符合格式的字符串:
data_latlon %>% rowwise() %>% mutate(latitude = ifelse(unit == 'deg_dec_min', conv_unit(latitude, from = 'deg_dec_min', to = 'dec_deg'), latitude)) %>% ungroup() %>% mutate(latitude = as.numeric(latitude)) # 统一转换为数值类型
方法2:使用case_when()结合类型转换
case_when()可以更清晰地定义分支逻辑,同时确保两边返回值类型一致:
data_latlon %>% mutate(latitude = case_when( unit == 'deg_dec_min' ~ conv_unit(latitude, from = 'deg_dec_min', to = 'dec_deg') %>% as.numeric(), TRUE ~ as.numeric(latitude) ))
两种方法最终都会得到正确的转换结果:
# A tibble: 6 × 3 latitude longitude unit <dbl> <dbl> <chr> 1 8.7261 -83.181 dec_deg 2 -16.3652 -62.016 dec_deg 3 -19.8881 -40.550 dec_deg 4 1.6705 75.905 deg_dec_min 5 0.0385 70.945 deg_dec_min 6 2.0393 72.686 deg_dec_min
内容的提问来源于stack exchange,提问作者Florencia Grattarola
相关产品推荐
相关产品推荐

