R:使用带 grepl 条件的 if 语句处理列中的数据

R: Processing data in columns using if statements with grepl conditioning

longtidue <- c('517W', '595W', '433W', '450E', '659E', '682W', '678W', '546E', '462W', '500W')
latitude <- c('291N','202N', '276N', '269S', '279N', '294N', '252N', '254S', '248N', '258N')
df <- data.frame(latitude, longitude)

是我正在使用的数据库的一个示例,它处理以以下格式出现的纬度和经度坐标:

240N, 707W, 267S, 130E

我需要处理这些坐标,以便它们可以用在采用以下形式坐标的模型中:

24.0, -70.7, -26.7, 13.0

(在模型中,北和东被认为是正方向。)

目标是能够 运行 向下查看整列,并确定单元格中是否存在 "N" 或 "S"。我想从那里删除字母,然后将剩余的数字除以 10 或 -10 以给出正确的符号。如果 N 或 S 都没有出现在列中,我希望代码单独保留单元格,这就是我在下面发布的示例代码末尾的 else 语句的原因。为了处理列中的所有数据,我尝试使用 elseif 语句,但我不确定如何让它工作。我最终进入了一个 for 循环,if 条件看起来像这样:

for (i in 1:nrow(df)) {
  if (grepl("N",df$latitude, fixed = TRUE)) {

    df$latitude <- gsub("N", "",df$latitude) & df$latitude <- df$latitude/(10)

   } else if (grepl("S",df$latitude, fixed = TRUE)) {

    df$latitude <- gsub("S", "",df$latitude) & df$latitude <- as.numeric(df$latitude) & df$latitude <- df$latitude/(-10)

   } else (df$latitude)
}

但这要么给我一个错误 df$latitude/(10) 说 "non-numeric argument to binary operator" 从数据从字符到数字的转换(?) and/or 一个警告 "the condition has length > 1 and only the first element will be used"。我对 R 和堆栈溢出也很陌生,所以如果我的代码可以更好地格式化,请告诉我。

提前致谢!

这是一个基本的 R 选项。首先,我们可以通过剥离最后一个方向字符,转换为数字,然后除以 10 来计算 latitude/longitude 值的绝对值。然后,我们有条件地翻转西方向和南方向的符号。

lng <- as.numeric(sub(".$", "", longitude)) / 10
lng <- ifelse(grepl("[WS]$", longitude), -1.0, 1.0) * lng
lng

[1] -51.7 -59.5 -43.3  45.0  65.9 -68.2 -67.8  54.6 -46.2 -50.0

数据:

longitude <- c('517W', '595W', '433W', '450E', '659E', '682W', '678W', '546E', '462W', '500W')

您遇到了一些问题:

  • 正如我在评论中提到的,您从 1 循环 inrow(df)。但是你没有在循环中提到 i,所以你在相同的输入上一次又一次地 运行 相同的代码。要成功使用 for 循环,您需要在其中放置一堆 [i],以便一次处理每个输入和输出。

  • 上面的循环方法很复杂,因为一个列只能有一种类型,所以你不能将 characterfactor 列转换为 numeric 一次一行---必须全有或全无。

  • 你好像对&有很大的误解。这行代码没有意义:df$latitude <- gsub("N", "",df$latitude) & df$latitude <- df$latitude/(10),它是用 & 连接在一起的两行代码。 A & B 并不意味着 "do A and do B",它的意思是“检查 AB 是否都为真。Return TRUE 如果它们是,和 FALSE 否则。如果你想做 A 然后做 B,只需将 A 放在一行上,然后 B 下一行

至于 好的 解决方案,在我写这篇文章时,您已经从 Tim 那里收到了一个不错的、简短的、矢量化的(不需要循环)解决方案。就这么做吧。