R: классификация записей на основе более чем 1 переменной - PullRequest
1 голос
/ 25 января 2020

Я пытаюсь классифицировать записи в таблице на основе их местоположения. Я разделил область на 9 квадратов одинаковой ширины и равной высоты (ширина! = Высота) и хотел бы создать новый столбец, в котором каждой записи присваивается метка, в зависимости от того, в какой квадрат она попадает. Это лучшее, что я мог сделать:

library(tidyverse)

set.seed(123)

latitude = 10*runif(100)
longitude = 10*runif(100)
locations = data.frame(latitude, longitude)

max_lat <- max(locations$latitude)
min_lat <- min(locations$latitude)
max_lng <- max(locations$longitude)
min_lng <- min(locations$longitude)

grid_num_lat <- 3
grid_num_lng <- 3

step_lat <- (max_lat-min_lat)/grid_num_lat
step_lng <- (max_lng-min_lng)/grid_num_lng

locations <- locations %>%
  mutate(grp_lat = ifelse(latitude <= (min_lat+step_lat), "A", 
                          ifelse(latitude <= (min_lat+(2*step_lat)), "B", 
                                 ifelse(latitude <= (min_lat+(3*step_lat)), "C", "NA")))
         , grp_lng = ifelse(longitude <= (min_lng+step_lng), "1", 
                            ifelse(longitude <= (min_lng+(2*step_lng)), "2", 
                                   ifelse(longitude <= (min_lng+(3*step_lng)), "3", "NA")))
         , grp_loc = paste(grp_lat, grp_lng))

Хотя это работает для моих нынешних целей, обновление кода было бы раздражающим, если бы я хотел разделить область на большее или меньшее количество квадратов. Конечно, есть более простой способ достичь этого?

Заранее спасибо

Ответы [ 2 ]

1 голос
/ 26 января 2020

Мы можем сделать это векторизованным способом с помощью findInterval

library(dplyr)
library(stringr)
out1 <- locations %>%
           mutate(grp_lat = LETTERS[findInterval(latitude, 
                          (min_lat + seq_len(3) *step_lat), 
                        rightmost.closed = TRUE)+ 1], 
                 grp_lng = findInterval(longitude, 
                          (min_lng + seq_len(3) *step_lng), 
                     rightmost.closed = TRUE)+ 1,
                  grp_loc = str_c(grp_lat, grp_lng, sep= ' ') )

-проверки с выходом OP

all.equal(out$grp_loc, out1$grp_loc)
#[1] TRUE
0 голосов
/ 25 января 2020

Вы можете заменить вложенные операторы ifelse на case_when следующим образом.

mutate(
  grp_lat=case_when(
    latitude <= (min_lat+step_lat)~"A",
    latitude <= (min_lat+(2*step_lat))~"B",
    latitude <= (min_lat+(3*step_lat))~"C",
    TRUE~NA),
  grp_lng = case_when(
    longitude <= (min_lng+step_lng)~"1",
    longitude <= (min_lng+(2*step_lng))~"2",
    longitude <= (min_lng+(3*step_lng))~"3"
    TRUE~NA), 
    grp_loc = paste(grp_lat, grp_lng))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...