繁体   English   中英

R:匹配两列以重建观察顺序(标记重获历史)

[英]R: matching two columns to reconstruct the order of observations (mark-recapture history)

我遇到的问题与我在此处发布的问题类似:

比较两列:逻辑-列1中的值是否也在列2中?

但是,数据格式略有不同。 常规数据结构是在3天时间内拍摄的一列照片中的列表,而与第1列中的照片匹配的另一列照片中的列表。其他信息是照片的拍摄日期,因此每天的个人都是相互排斥-特定个人每天最多只能拍摄一张照片(例如,在下面的示例中,“ A”永远不会与“ B”匹配,因为它们都是从第1天开始)。

photo <- c('A','B','C','D','E','F','G','H','I','J','K','K','L')
day <- c(1,1,1,1,2,2,2,3,3,3,3,3,3)
matching_photo <- c(NA,NA,NA,NA,NA,'A','B','E',NA,NA,'F','A','C')
DF <- data.frame(photo,day,matching_photo)

我正在寻找的数据输出是这样的:

serial.no <- c(1,2,3,4,5,6)
individuals <- c('A,F,K','B,G','C,L','D','E,H','I')
histories <- c('111','110','101','100','011','001')
finalDF <- data.frame(individuals,histories)

其中包括一个用于识别个人的序列号(由我组成,所以从1开始依次排列),对应于一列中每个个人的照片列表以及历史记录。 历史记录采用二进制格式,因此,如果在第1天观察到您,而直到第3天才再次出现,则您的历史记录将为“ 101”。 但是,如果只在第二天观察到您,则您的历史记录将为“ 010”。

我使用此特定数据集时遇到的问题之一(与上面链接的问题相比)是,如果某人连续三天被看到,那么该照片列中有该个人的两条记录(在“我上面的示例)匹配了前两天(“ A”和“ F”)的照片。 感谢提供的任何帮助。 谢谢!

这里最棘手的部分是找到所有同一个人的照片组。 如果照片A中的动物与照片G中的动物匹配,而照片L与照片G的匹配,则需要一种算法,该算法将照片A,G和L识别为全部链接。

这是网络分析中的经典问题,因此我转向igraph软件包,该软件包本身称为“网络分析和可视化”软件包。 它包含一个功能clusters() ,它将从“邻接矩阵”,编码节点之间的连接的矩阵中拉出链接的集群,如下所示:

 [1,] 1 . . . . . . . . . . .
 [2,] . 1 . . . . . . . . . .
 [3,] . . 1 . . . . . . . . .
 [4,] . . . 1 . . . . . . . .
 [5,] . . . . 1 . . . . . . .
 [6,] 1 . . . . 1 . . . . . .
 [7,] . 1 . . . . 1 . . . . .
 [8,] . . . . 1 . . 1 . . . .
 [9,] . . . . . . . . 1 . . .
[10,] . . . . . . . . . 1 . .
[11,] 1 . . . . 1 . . . . 1 .
[12,] . . 1 . . . . . . . . 1

上面的矩阵是数据的邻接矩阵。 12行和12列代表12张照片AL。 同一动物的照片标有1 其他单元格用点而不是0标记,因为这实际上是一种特殊表示形式,是为稀疏矩阵设计的,由Matrix包提供。 (如果您有庞大的数据集,则选择该表示形式: nlarge照片将产生一个具有nlarge^2单元的矩阵,这可能会淹没计算机的内存。)

在下面的代码中,第一个块构造邻接矩阵,第二个块为每只动物提取照片簇,第三个块将结果按您要求的形式放回去。

library(Matrix)
library(igraph)

# Construct an adjacency matrix, in which pairs of photos of the same  
# individual are encoded with 1's
photos <- as.character(unique(DF$photo))
n <- length(photos)
pairs <- subset(DF, !is.na(matching_photo), 
                select = c("photo", "matching_photo"))
pairs[] <- lapply(pairs, FUN=function(X) match(X, photos))
M <- 1 * with(pairs, sparseMatrix(i = c(seq_len(n), photo), 
                                  j = c(seq_len(n), matching_photo)))

# Extract vectors of photos of the same individual
(clust <- clusters(graph.adjacency(adjmatrix=M)))
# $membership
#  [1] 0 1 2 3 4 0 1 4 5 6 0 2
# $csize
# [1] 3 2 2 1 2 1 1
# $no
# [1] 7

# Process results of clustering to construct output data.frame
DF2 <- cbind(individual = clust$membership, 
             subset(DF, !duplicated(photo), select=c("photo", "day")))
grps <- tapply(DF2$photo, DF2$individual, paste, collapse=",")
days <- tapply(DF2$day, DF2$individual, 
               FUN=function(X) paste((1 * unique(DF$day) %in% X), collapse=""))
data.frame(individual = as.numeric(names(grps)), photos = grps, days=days)
#   individual photos days
# 0          0  A,F,K  111
# 1          1    B,G  110
# 2          2    C,L  101
# 3          3      D  100
# 4          4    E,H  011
# 5          5      I  001
# 6          6      J  001

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM