英文:
How to apply an if statement on each individual row in R?
问题
I have a datasets of X and Y coordinates that are in packed DMS format and I want to transform them to decimal degrees. To do that I have to separate the degrees, minutes and seconds. It would be straightforward if all the numbers in the column had the same length, but some have 7 and some 8.
The data set looks something like this:
coords$X <- c(100942.2, 67942.2, 229942.2, 239942.2, 52942.2)
I had the idea to use an if else
statement to check the length of each number using this code:
if (nchar(coords$X == 8)){
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))
}
But I am getting an error:
Error in if (nchar(coords$XCoordinatePlot == 8)) { :
the condition has length > 1
Is there a way to make this work?
英文:
I have a datasets of X and Y coordinates that are in packed DMS format and I want to transform them to decimal degrees. To do that I have to separate the degrees, minutes and seconds. It would be straightforward if all the numbers in the column had the same length, but some have 7 and some 8.
The data set looks something like this:
coords$X <- c(100942.2, 67942.2, 229942.2, 239942.2, 52942.2)
I had the idea to use an if else
statement to check the length of each number using this code:
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))
}
But I am getting an error:
Error in if (nchar(coords$XCoordinatePlot == 8)) { :
the condition has length > 1
Is there a way to make this work?
答案1
得分: 2
Sure, here is the translated code:
像这样吗?使用 `sprintf` 使所有数字具有相同的长度,然后获取子字符串。
注意:下面的函数会丢弃小数部分。
X <- c(100942.2, 67942.2, 229942.2, 239942.2, 52942.2)
fun <- function(x) {
y <- sprintf("%06d", as.integer(x))
D <- as.integer(substr(y, 1, 2))
M <- as.integer(substr(y, 3, 4))
S <- as.integer(substr(y, 5, 6))
cbind(D, M, S)
}
fun(X)
#> D M S
#> [1,] 10 9 42
#> [2,] 6 79 42
#> [3,] 22 99 42
#> [4,] 23 99 42
#> [5,] 5 29 42
在 2023-04-13 创建,使用 reprex v2.0.2
英文:
Something like this? Use sprintf
to have all numbers of the same length, then get the substrings.
Note: The function below discards the decimal part.
X <- c(100942.2, 67942.2, 229942.2, 239942.2, 52942.2)
fun <- function(x) {
y <- sprintf("%06d", as.integer(x))
D <- as.integer(substr(y, 1, 2))
M <- as.integer(substr(y, 3, 4))
S <- as.integer(substr(y, 5, 6))
cbind(D, M, S)
}
fun(X)
#> D M S
#> [1,] 10 9 42
#> [2,] 6 79 42
#> [3,] 22 99 42
#> [4,] 23 99 42
#> [5,] 5 29 42
<sup>Created on 2023-04-13 with reprex v2.0.2</sup>
答案2
得分: 2
以下是翻译好的部分:
有多种可能的方法可以转换这些数据。我认为最好的方法是使用除法和余数:
coords$degrees <- coords$X %/% 10000
coords$min <- (coords$X %% 10000) %/% 100
coords$sec <- coords$X %% 100
如果您想使用if/else语句,您可以将它放在一个函数内,并使用purrr包中的map_df()
将其应用于每个元素:
library(purrr)
library(stringr)
convert <- function(x) {
if (nchar(x) == 8){
degrees <- as.numeric(str_sub(x, 1, 2))
min <- as.numeric(substr(x, 3, 4))
sec <- as.numeric(substr(x, 5, 7))
} else {
degrees <- as.numeric(str_sub(x, 1, 1))
min <- as.numeric(substr(x, 2, 3))
sec <- as.numeric(substr(x, 4, 5))
}
return(data.frame(degrees, min, sec))
}
cbind(coords, map_df(coords$X, convert))
(请注意,您的函数不会四舍五入,而是去除秒的小数部分。)
英文:
There are multiple possible ways to convert these data. The best way in my opinion would be to use division and remainders:
coords$degrees <- coords$X %/% 10000
coords$min <- (coords$X %% 10000) %/% 100
coords$sec <- coords$X %% 100
If you want to use your if/else statement, you could place it inside a function and use map_df()
from the package purrr to apply it to each element:
library(purrr)
library(stringr)
convert <- function(x) {
if (nchar(x) == 8){
degrees <- as.numeric(str_sub(x, 1, 2))
min <- as.numeric(substr(x, 3, 4))
sec <- as.numeric(substr(x, 5, 7))
} else {
degrees <- as.numeric(str_sub(x, 1, 1))
min <- as.numeric(substr(x, 2, 3))
sec <- as.numeric(substr(x, 4, 5))
}
return(data.frame(degrees, min, sec))
}
cbind(coords, map_df(coords$X, convert))
(Note that your function does not round but strip the decimal of secs.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论