Очистка исходных данных с дубликатами, но с разным уровнем факторов - PullRequest
0 голосов
/ 10 января 2020

У меня есть некоторые данные ГИС с источниками и пунктами назначения (OD) и информацией о времени суток OD. Я намеревался составить карту этого и раскрасить OD по времени суток информации.

Одна вещь состоит в том, что некоторые OD находятся в наборе данных как днем, так и ночью, и, возможно, в другом порядке. Я хотел бы отметить их по-разному, например, «День / Ночь»

Есть ли простой способ сделать это? МОЙ MWE - только один ОД, но я должен был бы идентифицировать это среди нескольких других. Мне удается найти дубликаты независимо от порядка, но я не знаю, как выяснить, есть ли в них временные случаи и как их заменить на «День / Ночь»

library(data.table)
Origin<-c("London", "Paris", "Lisbon", "Madrid", "Berlin", "London")
Destination<-c("Paris", "London", "Berlin","Lisbon", "Lisbon", "Paris")
Time=factor(c("Day", "Night", "Day", "Day/Night","Day", "Day/Night"))
dt<-data.table(Origin=Origin, Destination=Destination, Time=Time)
#duplicates regardless of order
dat.sort = t(apply(dt[,.(Origin,Destination)], 1, sort))
dt[duplicated(dat.sort) | duplicated(dat.sort, fromLast=TRUE),]

Ответы [ 2 ]

0 голосов
/ 13 января 2020

Спасибо за решение dplyr от @Nareman Darwisch, которое вдохновило меня на решение с data.table

Я создаю новую переменную в качестве уникального идентификатора для каждого источника назначения

dat.sort = t(apply(dt[,.(Origin,Destination)], 1, sort))
dt.temp<-data.table(dat.sort)
dt.temp[,unique.name:=paste(V1,V2)]
dt$unique.name<-factor(dt.temp$unique.name)

Тогда я могу либо рассчитать длину уникальных вхождений фактора по группе, либо совпадать они более одного раза с любым из 3 уровней. Исходя из этого, я могу перекодировать метки с уровнем «День / Ночь» всякий раз, когда длина> 1 или другое условие ИСТИНА

dt[,No.levels:=length(unique(c(Time))), by=unique.name]
dt[,No.levels.logi:=sum(c(Time) %in% c(1:3))>1 , by=unique.name]

То, что я хотел бы понять, как я мог бы использовать логический Условие в духе смотреть на уровни по группам и сравнивать их с делами, которые я хочу.

dt[,No.levels.logi:=sum(levels(Time) %in% c("Day", "Night"))>1 , by=unique.name]

Но я думаю, что команда уровней всегда дает мне все три уровня.

0 голосов
/ 11 января 2020

Вы можете сделать это с помощью пакета dplyr следующим образом:

Не стесняйтесь изменять условия в соответствии с вашими потребностями.

library(data.table)
library(dplyr)

# Creating data
dt <- 
  data.table(
    Origin = c("London", "Paris", "Italy", "Spain", "Portugal", "Poland"),
    Destination = c("Paris", "London", "Norway", "Portugal", "Spain", "Spain"),
    Time = c("Day", "Night", "Day", NA_character_, NA_character_, NA_character_)
  )

dt

# Origin Destination  Time
# London   Paris      Day
# Paris    London     Night
# Italy    Norway     Day
# Spain    Portugal   <NA>
# Portugal Spain      <NA>
# Poland   Spain      <NA>

dt %>%
  # pmin and pmax are used to sort the 2 columns
  # in order to group by them regardless to their order
  group_by(Origin2 = pmin(Origin, Destination), 
           Destination2 = pmax(Origin, Destination)) %>%
  mutate(count = n(), # To check if Origin/destination are repeated or not
         row = row_number(), # Place holder to know if it was first to repeat or second
         # If not repeated then make Time = Day
         # If repeated and first occurance then Time = Day
         # If repeated and second occurance then Time = Night
         Time = case_when(count == 1 ~ "Day",
                          count == 2 & row == 1 ~ "Day",
                          count == 2 & row == 2 ~ "Night")) %>%
  ungroup() %>%
  select(Origin, Destination, Time)

# Origin   Destination Time 
# <chr>    <chr>       <chr>
#   1 London   Paris       Day  
# 2 Paris    London      Night
# 3 Italy    Norway      Day  
# 4 Spain    Portugal    Day  
# 5 Portugal Spain       Night
# 6 Poland   Spain       Day  
...