[英]R: matching two columns to reconstruct the order of observations (mark-recapture history)
我遇到的问题与我在此处发布的问题类似:
但是,数据格式略有不同。 常规数据结构是在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.