R: сопоставление двух столбцов для восстановления порядка наблюдений (история меток-повторных захватов) - PullRequest
2 голосов
/ 12 января 2012

У меня проблема, аналогичная той, которую я выложил здесь:

Сравнение двух столбцов: логическое - это значение из столбца 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), список фотографий, которыесоответствуют каждому человеку в столбце и истории.Истории следуют в двоичном формате, так что если вы наблюдались в первый день, а не снова до третьего дня, ваша история была бы «101».Но если бы вас наблюдали только на второй день, ваша история была бы «010».

Одна из проблем, с которыми я сталкиваюсь с этим конкретным набором данных (по сравнению с проблемой, связанной выше), заключается в том, что если человеквиден 3 дня подряд, в столбце фотографий есть две записи для этого человека («K» в моем примере выше), соответствующие фотографиям обоих предыдущих дней («A» и «F»).Я ценю любую помощь, оказанную.Спасибо!

1 Ответ

1 голос
/ 13 января 2012

Сложная задача - найти те группы фотографий, которые принадлежат одному человеку.Если животное на фотографии 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 фотографий, AL.Фотографии того же животного помечены 1.Другие ячейки отмечены точками, а не 0, потому что это на самом деле специальное представление, разработанное для разреженных матриц и предоставляемое пакетом Matrix.(Я выбрал это представление в случае, если у вас огромный набор данных: nlarge photos создаст матрицу с 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
...