含空格的字符型坐标数据清洗:如何转数值型且无NA?
解决方案:混乱DMS坐标清洗与转换
步骤1:统一格式并修正已知录入错误
先处理样本中的分隔符混乱(空格、*、点)和度数录入错误(如"19* 9"/"19 9"应为"96"),将所有条目统一为度:分:秒格式:
library(stringr) library(purrr) # 模拟原始数据 lon_samples <- c("096 34 01.63", "096 35 46.93", "96.48.838", "19* 9 41.715", "19 9 15.922") # 初步清洗:修正度数错误+统一分隔符 lon_step1 <- lon_samples %>% # 修正度数录入错误:把"19* 9"或"19 9"替换为正确的"96" str_replace("^19[*\\s]9", "96") %>% # 将所有非数字/非小数点的字符替换为冒号 str_replace_all("[^0-9.]", ":") %>% # 处理可能出现的连续冒号 str_replace_all("::+", ":")
此时输出的初步清洗结果与要求一致:"096:34:01.63" "096:35:46.93" "96:48:838" "96:41:715" "96:15:922"
步骤2:修正秒数/分数溢出问题
针对秒数远超60的情况,通过进位将多余的秒转换为分,多余的分转换为度,得到标准DMS格式:
# 修正DMS溢出 lon_step2 <- map_chr(lon_step1, function(x) { dms <- str_split(x, ":")[[1]] %>% as.numeric() d <- dms[1] m <- dms[2] s <- dms[3] # 秒转分:计算溢出的分和剩余秒数 extra_min <- floor(s / 60) s_corr <- round(s %% 60, 2) # 分转度:计算溢出的度和剩余分数 extra_deg <- floor((m + extra_min) / 60) m_corr <- (m + extra_min) %% 60 # 修正后的度数 d_corr <- d + extra_deg # 拼接为标准DMS字符串 sprintf("%d:%d:%.2f", d_corr, m_corr, s_corr) })
输出的最终DMS格式与提供的样本匹配:"96:34:1.63" "96:35:46.93" "96:48:13.97" "96:41:11.92" "96:15:15.37"
步骤3:转换为Numeric类十进制坐标
通过手动计算将DMS转换为十进制数值,确保无NA产生(若前面清洗彻底,不会出现转换失败):
# DMS转十进制数值 lon_decimal <- map_dbl(lon_step2, function(x) { dms <- str_split(x, ":")[[1]] %>% as.numeric() # 公式:十进制 = 度 + 分/60 + 秒/3600,注意正确经度为负 - (dms[1] + dms[2]/60 + dms[3]/3600) }) # 查看结果(无NA) lon_decimal # [1] -96.56712 -96.59637 -96.80388 -96.68664 -96.25427
关键注意事项
- 若有其他度数录入错误,可扩展
str_replace规则覆盖更多情况 - 若秒数的小数位数不统一,可调整
round或sprintf的精度参数 - 纬度的清洗逻辑完全一致,只需替换度数修正规则(如对应正确纬度值)
内容的提问来源于stack exchange,提问作者Nathanial O'Dell
相关产品推荐
相关产品推荐

