You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中对每行数据应用if语句?解决DMS转十进制度报错

问题:紧凑DMS坐标转十进制度数时的条件判断报错

我有一组采用紧凑DMS格式的X坐标数据,需要转换为十进制度数,得先分离度、分、秒,但列中数字长度不一致(部分7位、部分8位),数据集示例:

coords$X <- c(100942.2, 67942.2, 229942.2, 239942.2, 52942.2)

我尝试用if else语句检查每个数字的长度,代码如下:

if (nchar(coords$X == 8)){0
coords$degrees.x <- as.numeric(str_sub(coords$X, 1, 2))
coords$min.x <- as.numeric(substr(coords$X, 3, 4))
coords$sec.x <- as.numeric(substr(coords$XC, 5, 7))
} else {
  coords$degrees.x <- as.numeric(str_sub(coords$X, 1, 1))
  coords$min.x <- as.numeric(substr(coords$X, 2, 3))
  coords$sec.x <- as.numeric(substr(coords$X, 4, 5))
}

但出现报错:

Error in if (nchar(coords$XCoordinatePlot == 8)) { : 
  the condition has length > 1

需要解决这个问题,实现逐行应用条件判断。


解决方案

问题根源

  1. if语句的局限性:基础if是标量判断,只能处理单个逻辑值,而coords$X是向量,nchar(coords$X) ==8会返回布尔向量,导致报错。
  2. 逻辑表达式错误:原代码nchar(coords$X == 8)是先判断数值是否等于8再取长度,完全不符合需求,正确写法是nchar(coords$X) ==8。
  3. 变量名笔误:代码中substr(coords$XC, 5, 7)的XC是错误变量名,应为X。

方法1:向量化ifelse处理

用ifelse对向量每个元素做判断,替代标量if:

library(stringr)

# 转字符串避免科学计数法干扰
coords$X_str <- as.character(coords$X)

# 逐元素分离度分秒
coords$degrees.x <- ifelse(nchar(coords$X_str) == 8,
                           as.numeric(str_sub(coords$X_str, 1, 2)),
                           as.numeric(str_sub(coords$X_str, 1, 1)))

coords$min.x <- ifelse(nchar(coords$X_str) == 8,
                       as.numeric(str_sub(coords$X_str, 3, 4)),
                       as.numeric(str_sub(coords$X_str, 2, 3)))

coords$sec.x <- ifelse(nchar(coords$X_str) == 8,
                       as.numeric(str_sub(coords$X_str, 5, 8)), # 包含小数部分
                       as.numeric(str_sub(coords$X_str, 4, 7)))

# 转换为十进制度数
coords$X_decimal <- coords$degrees.x + coords$min.x/60 + coords$sec.x/3600

方法2:补前导零统一长度(更简洁鲁棒)

先给所有字符串补前导零至8位,直接截取固定位置,无需条件判断:

library(stringr)

coords$X_str <- str_pad(as.character(coords$X), width = 8, side = "left", pad = "0")

coords$degrees.x <- as.numeric(str_sub(coords$X_str, 1, 2))
coords$min.x <- as.numeric(str_sub(coords$X_str, 3, 4))
coords$sec.x <- as.numeric(str_sub(coords$X_str, 5, 8))

coords$X_decimal <- coords$degrees.x + coords$min.x/60 + coords$sec.x/3600

方法3:dplyr的case_when(适合数据框操作)

用tidyverse工具链的case_when清晰处理多条件:

library(dplyr)
library(stringr)

coords <- coords %>%
  mutate(X_str = as.character(X),
         degrees.x = case_when(
           nchar(X_str) ==8 ~ as.numeric(str_sub(X_str,1,2)),
           TRUE ~ as.numeric(str_sub(X_str,1,1))
         ),
         min.x = case_when(
           nchar(X_str) ==8 ~ as.numeric(str_sub(X_str,3,4)),
           TRUE ~ as.numeric(str_sub(X_str,2,3))
         ),
         sec.x = case_when(
           nchar(X_str) ==8 ~ as.numeric(str_sub(X_str,5,8)),
           TRUE ~ as.numeric(str_sub(X_str,4,7))
         ),
         X_decimal = degrees.x + min.x/60 + sec.x/3600)

内容的提问来源于stack exchange,提问作者starski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 09:13:27