【问题标题】:Cleaning Origin and Destination data with duplicates but different factor level清理具有重复但不同因子级别的起点和终点数据
【发布时间】:2020-04-28 03:56:28
【问题描述】:

我有一些包含起点和终点 (OD) 的 GIS 数据以及有关 OD 当天时间的信息。我打算为此制作一张地图,并根据一天中的时间信息为 OD 着色。

有一点是,有些 OD 在数据集中有白天和黑夜,而且可能有不同的顺序。我想用不同的方式标记它们,例如“白天/黑夜”

有没有简单的方法来做到这一点?我的 MWE 只是一个 OD,但我需要在其他几个中识别它。无论顺序如何,我都可以设法找到重复项,但我不知道如何找出是否有两种时间情况以及如何用“日/夜”替换它们

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 个国家/地区在一天时间有两条记录的情况?
  • 我正在尝试查找在白天和晚上运行的同一起点目的地的记录,我想将它们重新编码为“夜间/白天”

标签: r duplicates data.table gis data-cleaning


【解决方案1】:

您可以使用 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  

【讨论】:

    【解决方案2】:

    感谢@Nareman Darwisch 的 dplyr 解决方案,它给了我data.table 解决方案的灵感

    我正在创建一个新变量作为每个起点目的地的唯一 ID

    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 或其他条件为 TRUE,我就可以使用“日/夜”级别重新编码标签

    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]
    

    但我猜levels命令总是给我所有三个级别。

    【讨论】:

      【解决方案3】:

      如果我理解正确,OP想要

      • 无论始发地和目的地的顺序如何,都可以识别城市对,例如伦敦-巴黎与巴黎-伦敦属于同一城市对
      • 如果操作城市对,则折叠单独的行Day Night Day/Night
      • 或更新原始数据集

      这就是我要做的:

      library(data.table)
      dt <- data.table(Origin, Destination, Time)
      # add city pair as unique grouping variable
      dt[, Pair := paste(pmin(Origin, Destination), pmax(Origin, Destination), sep = "-")][]
      # identify city pairs which are operated day and night
      pairs_DN <- dt[, all(c("Day", "Night") %in% Time) | "Day/Night" %in% Time, by = Pair][(V1), .(Pair)]
      # update original dataset by an update join
      dt[pairs_DN, on = "Pair", Time := "Day/Night"][]
      
         Origin Destination      Time          Pair
      1: London       Paris Day/Night  London-Paris
      2:  Paris      London Day/Night  London-Paris
      3: Lisbon      Berlin       Day Berlin-Lisbon
      4: Madrid      Lisbon Day/Night Lisbon-Madrid
      5: Berlin      Lisbon       Day Berlin-Lisbon
      6: London       Paris Day/Night  London-Paris
      

      关键是确定满足第二个要求的城市对:

      dt[, all(c("Day", "Night") %in% Time) | "Day/Night" %in% Time, by = Pair]  
      
                  Pair    V1
      1:  London-Paris  TRUE
      2: Berlin-Lisbon FALSE
      3: Lisbon-Madrid  TRUE
      

      因此,无需处理因子水平。顺便说一句,因子水平是整个列的属性,在子集或分组时不会改变。改变的是子集或组中使用了哪些级别。

      pairs_DN 包含这些城市对的唯一键

                  Pair
      1:  London-Paris
      2: Lisbon-Madrid
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-07
        • 2013-12-14
        • 2021-10-05
        • 2016-12-16
        • 1970-01-01
        • 2012-07-24
        • 1970-01-01
        • 2014-11-28
        相关资源
        最近更新 更多