根据多个列的条件连接两个表

问题描述 投票:-1回答:1

我正在使用来自野生动物的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将一个Animal_ID列添加到指示Animal_ID的GPS项圈数据中。我的预期输出如下:

   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
r join merge
1个回答
0
投票

我已经为我的问题提出了一个相当笨重的解决方案,但它确实有效。见下文:

#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)

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

© www.soinside.com 2019 - 2024. All rights reserved.