【问题标题】:Joining two tables based on criteria across multiple columns根据跨多个列的条件连接两个表
【发布时间】:2017-12-18 23:12:18
【问题描述】:

我正在处理来自野生动物的 GPS 项圈数据。 GPS 项圈由序列号识别。在几年的时间里,一个 GPS 项圈可以用于多个动物。我需要为 GPS 项圈中的每个数据点分配动物 ID。应将动物 ID 分配给正确的项圈编号,但仅限于捕获日期或之后以及该动物死亡日期(如果适用)当天或之前拍摄的位置。

以下是我的数据的示例。

当 GPS 项圈数据通过卫星下载时,格式如下:

   CollarSerialNumber Latitude Longitude       Date
1               36542 44.95511 -107.5431 2016-02-18
2               36542 44.94927 -107.5855 2016-02-19
3               36542 44.95027 -107.5838 2016-02-20
4               36542 44.96125 -107.5831 2016-02-20
5               36542 44.95949 -107.5854 2016-02-21
6               36542 44.95233 -107.5717 2016-02-21
7               36542 44.95743 -107.5664 2016-02-22
8               36542 44.96124 -107.5840 2016-02-22
9               36542 44.96322 -107.5799 2016-02-22
10              36542 44.95912 -107.5857 2016-02-23
11              36545 44.95263 -107.5207 2016-02-17
12              36545 44.95278 -107.5202 2016-02-17
13              36545 44.95366 -107.5481 2016-02-18
14              36545 44.93453 -107.5940 2016-02-19
15              36545 44.94563 -107.5823 2016-02-19
16              36545 44.95020 -107.5836 2016-02-20

我有一个单独的数据框,其中包含动物的捕获日期(即项圈戴在动物身上的日期)、动物 ID 和死亡日期。

  Animal_ID Collar_Serial Capture_Date  Mort_Date
1    16-046         36542   2016-02-18 2016-02-20
2    16-047         36542   2016-02-21         NA
3    16-048         36545   2016-02-17         NA

因此,我需要根据 Collar Serial # 和 Capture and Mortality Dates 在 GPS 项圈数据中添加一个 Animal_ID 列来指示 Animal_ID。我的预期输出如下:

   CollarSerialNumber Latitude Longitude       Date    Animal_ID
1               36542 44.95511 -107.5431 2016-02-18    16-046 
2               36542 44.94927 -107.5855 2016-02-19    16-046 
3               36542 44.95027 -107.5838 2016-02-20    16-046 
4               36542 44.96125 -107.5831 2016-02-20    16-046 
5               36542 44.95949 -107.5854 2016-02-21    16-047
6               36542 44.95233 -107.5717 2016-02-21    16-047
7               36542 44.95743 -107.5664 2016-02-22    16-047
8               36542 44.96124 -107.5840 2016-02-22    16-047
9               36542 44.96322 -107.5799 2016-02-22    16-047
10              36542 44.95912 -107.5857 2016-02-23    16-047
11              36545 44.95263 -107.5207 2016-02-17    16-048
12              36545 44.95278 -107.5202 2016-02-17    16-048
13              36545 44.95366 -107.5481 2016-02-18    16-048
14              36545 44.93453 -107.5940 2016-02-19    16-048
15              36545 44.94563 -107.5823 2016-02-19    16-048
16              36545 44.95020 -107.5836 2016-02-20    16-048

【问题讨论】:

  • 您尝试过什么吗?你在哪里卡住了?
  • 你的问题不清楚(对我来说)。 GPS数据中的Date是否需要匹配Capture_DateMort_Date?您能否编辑您的问题以包含您提供的示例数据的预期输出。
  • @MauritsEvers 我已经编辑了预期输出的问题。希望现在更清楚了。
  • @MrFlick 我在论坛中搜索有类似问题的人,并阅读了合并和加入功能,但我没有取得任何进展......

标签: r join merge


【解决方案1】:

我想出了一个相当笨拙的解决方案来解决我的问题,但它确实有效。见下文:

#get all Animal_IDs from capture dataset
allID = unique(capdat$Animal_ID)

#create list to hold data frames, one df for each animalID
df.list <- as.list(rep("", length(allID)))

#loop through each animal ID, find matching collar serial #, capture date, 
#and mortality date (if applicable)
for (i in 1:length(allID)){
  ID.i = allID[i]
  ser.i <- pull(capdat[capdat$Animal_ID == ID.i, 4])
  capdate.i = pull(capdat[capdat$Animal_ID == ID.i, 2])
  mortdate.i = pull(capdat[capdat$Animal_ID == ID.i, 11])

  ifelse(is.na(mortdate.i), 
        df.list[[i]] <- dat[(dat$CollarSerialNumber == ser.i & 
                          dat$Date > capdate.i) ,],
        df.list[[i]] <- dat[(dat$CollarSerialNumber == ser.i & 
                          dat$Date > capdate.i & dat$Date < mortdate.i) ,])
  df.list[[i]]$Animal_ID = ID.i
  }

#merge list into a single data frame
df <- ldply(df.list, data.frame)

如果有人能提出更优雅的解决方案,我很乐意看到它!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-18
    • 2015-10-09
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    相关资源
    最近更新 更多