对于复杂的帖子提前表示歉意;这是一个(非常令人沮丧的)问题,我已经困扰了很长一段时间了。
我有一个数据集,正处于清理的最后步骤。我试图克服的最后一个障碍与坐标信息的输入方式有关 - 经度和纬度的格式是伪 DMS 和十进制形式的混合,以及一些常见的混乱。这是经度列的示例:
"096 34 01.63" "096 35 46.93" "96.48.838" "19* 9 41.715" "19 9 15.922"
如您所见,秒数远远超过 60、
"19* 9 41.715" "19 9 15.922"
中存在杂散小数、不正确的度值(19 9 而不是 -96)、标牌问题等
这两列的类别都是字符。我尝试将类更改为数字,因为我必须对秒进行一些算术才能修复它们(见上文),但这引入了 NA;我认为这是条目中空格的结果。作为参考,这就是示例应该在完成初始步骤后的样子:
"096:34:01.63" "096:35:46.93" "96:48:838" "199:41:715" "199:15:922"
这就是我完全清洁后的样子:
"-96:34:1.63" "-96:35:46.93" "-96:48:13.97" "-96:41:11.91" ""-96:15:15.36"
有什么方法可以在不引入 NA 的情况下完成将列转换为数字类的初始步骤吗?
首先,我假设您所需的输出中的一些差异是拼写错误:负数(不确定)和 19-to-199-to-96。我认为以下结果是一致的。
消除
*
噪音。
标准化太多点,每个字符串只允许一个。例如,
"96.48.838"
-> "96 48.838"
gsub("\\.(?=[^.]*[.])", " ", "11.22.33.44.55", perl=TRUE)
# [1] "11 22 33 44.55"
将DM转换为DMS;例如,
"96 48.838"
-> "96 48 50.28"
,因为 0.838
分钟是 50.28
秒。
(假设)将
0
-填充添加到度/分钟,将秒限制为 3 位小数。
vec <- c("096 34 01.63", "096 35 46.93", "96.48.838", "19* 9 41.715", "19 9 15.922")
gsub("*", "", vec, fixed=TRUE) |>
gsub("\\.(?=[^.]*[.])", " ", x = _, perl=TRUE) |>
strsplit(" ") |>
sapply(function(X) {
X <- as.numeric(X)
if (length(X) == 2) X <- c(floor(X[1:2]), X[2] %% 1 * 60)
paste(c(sprintf("%02.0f", X[1:2]),
sprintf("%02.3f", X[3])),
collapse = ":")
})
# [1] "96:34:1.630" "96:35:46.930" "96:48:50.280" "19:09:41.715" "19:09:15.922"