2015-11-05 1 views
0

У меня есть data.frame A с +100 000 строк, содержащих информацию о местоположении (Lat = широта, Lon = долгота) и другой data.frame B с + 500 строк, содержащих лимиты для географических районов (области не пересекаются).Вернуть вектор, основанный на значениях в одном файле данных.файла и условий в другом

Как я могу создать функцию, которая возвращает имя места из B на основе местоположений в A?

Я хотел R вернуть вектор топонимов, когда место существует в B, «не назначен» в тех случаях, когда место не существует, и NA в тех случаях, когда либо Lat или Lon отсутствует в A

Пример:

dataA <- structure(list(Lat = c(60L, 63L, 0L, 75L, NA, 71L, 70L), Lon = c(-70L, 
-66L, 5L, -100L, 80L, -61L, -150L)), .Names = c("Lat", "Lon"), class = "data.frame", row.names = c(NA, 
-7L)) 

dataB <- structure(list(Region = structure(c(2L, 3L, 1L), .Label = c("Beaufort Sea", 
"Hudson Strait", "North West Passage"), class = "factor"), Lat.min = c(55, 
70, 69.5), Lat.max = c(65L, 80L, 72L), Lon.min = c(-75L, -120L, 
-160L), Lon.max = c(-60L, -60L, -120L)), .Names = c("Region", 
"Lat.min", "Lat.max", "Lon.min", "Lon.max"), class = "data.frame", row.names = c(NA, 
-3L)) 

## I would like to test for each row in dataA: 

i <- 1 ## i <- 1:nrow(dataB) 
dataA$Lat > dataB$Lat.min[i] & dataA$Lat < dataB$Lat.max[i] & 
dataA$Lon > dataB$Lon.min[i] & dataA$Lon < dataB$Lon.max[i] 

## and return                            
dataB$Region[i] ## only once for each row of dataA,                   
##unless is.na(dataA$Lat) | is.na(dataA$Lon), then return(NA), 
##and if a row in dataA does not match any row in dataB, then return "not assigned" 

## The result should look something like: 
c("Hudson Strait", "Hudson Strait", "not assigned", "North West Passage", 
NA, "North West Passage", "Beaufort Sea") 

Что я пробовал: я решил аналогичные проблемы с использованием функции ifelse ранее, но в данном случае мой условный data.frame слишком большой, чтобы сделать это вручную. Я также попытался выполнить split data.frame A и запустить условный цикл for, но не смог выяснить, как сформулировать цикл for. Если я использую оператор if внутри цикла, мой цикл возвращает столько значений, сколько строк в значениях B для каждой строки в A. У меня также есть ощущение, что запуск цикла for для этого набора данных займет много времени, а не говоря размер расщепленной data.frame А. Там должно лучший способ сделать это ...

ответ

0

Вот один, конечно, не самый изящный, способ сделать это:

z <- lapply(1:nrow(dataB), function(i){ 
    ifelse(is.na(dataA$Lat) | is.na(dataA$Lon), "Missing", 
ifelse(dataA$Lat > dataB$Lat.min[i] & dataA$Lat < dataB$Lat.max[i] & 
dataA$Lon > dataB$Lon.min[i] & dataA$Lon < dataB$Lon.max[i], 
as.character(dataB$Region[i]), NA)) 
    }) 

z <- do.call(rbind,z) 

apply(z, 2, function(j) { 
    out <-j[!is.na(j)] 
    if(length(out) == nrow(z)) { 
    return(NA)} else { 
     if(length(out) > 0) { 
     return(out)} else { 
     return("Not assigned") 
     }} 
    }) 

# [1] "Hudson Strait" "Hudson Strait" "Not assigned" "North West Passage" 
# NA "North West Passage" "Beaufort Sea" 

Может кто-то имеет более элегантное решение?

Смежные вопросы