Reputation: 3
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)
is an example of a database that I'm working with that deals with coordinates in latitude and longitude that appear in the format:
240N, 707W, 267S, 130E
I need to process these coordinates so they can be used in a model that takes coordinates in the form:
24.0, -70.7, -26.7, 13.0
(In the model, North and East are considered the positive directions.)
The goal is to be able to run down the entire column, and to identify if there is either an "N" or an "S" in the cell. From there I want to remove the letter and then divide the remaining number by either 10 or -10 to give it the correct sign. If neither N or S appear in the column, I want the code to leave the cell alone, which is the reasoning for the else statement at the end of the sample code I've posted below. In order to process all the data in the columns, I've tried using an elseif statement but I wasn't exactly sure how to get it to work. I ended up at a for loop with if conditions that look like this:
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)
}
But this either gives me an error with df$latitude/(10) saying "non-numeric argument to binary operator" from the conversion of the data from character to numeric(?) and/or a warning that the "the condition has length > 1 and only the first element will be used". I'm also very new to R and stack overflow for that matter, so if my code could be formatted better, let me know.
Thanks in advance!
Upvotes: 0
Views: 68
Reputation: 145765
You've got a few problems:
As I mentioned in comments, you loop over i
from 1
to nrow(df)
. But you don't mention i
inside the loop, so you're running the same code on the same inputs again and again. To use a for
loop successfully, you'd need to have a bunch of [i]
s in there, to handle each input and output one at a time.
The loop approach above is complicated by the fact that a column can only have one type, so you can't covert the character
or factor
column to numeric
one row at a time---that has to be all or nothing.
You seem to have a major misunderstanding with &
. This line of code makes no sense: df$latitude <- gsub("N", "",df$latitude) & df$latitude <- df$latitude/(10)
, it's two separate lines joined together with an &
. The A & B
doesn't mean "do A
and do B
", it means "check if A
and B
are both true. Return TRUE
if they are, and FALSE
otherwise. If you want to do A
and then do B
, just put A
on a line and B
on the next line
As far as a good solution, as I've been writing this you've already received a nice, short, vectorized (no loop needed) solution from Tim. Just do that.
Upvotes: 0
Reputation: 520988
Here is one base R option. First we can compute the absolute value of the latitude/longitude value by stripping the last directional character, converting to numeric, and then dividing by 10. Then, we conditionally flip the sign for west and south directions.
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
Data:
longitude <- c('517W', '595W', '433W', '450E', '659E', '682W', '678W', '546E', '462W', '500W')
Upvotes: 1