Сравните одну строку со всеми другими строками в файле, используя R - PullRequest
2 голосов
/ 03 сентября 2011

У меня есть файл, подобный приведенному ниже:

P1 A,B,C    
P2 B,C,D,F    
P3 C,D,E,F  

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

P1 P2 2    
P1 P3 1    
P2 P3 3   

СпасибоВы,
S

Ответы [ 2 ]

4 голосов
/ 03 сентября 2011

Неясно, откуда берутся исходные данные, поэтому я предположил, что вы читаете данные в data.frame, как показано ниже:

x <- data.frame(V1 = c("a", "b", "c"), 
                V2 = c("b", "c", "d"), 
                V3 = c("c", "d", "e"),
                V4 = c(NA, "f", "f"),
                stringsAsFactors = FALSE
                )

row.names(x) <- c("p1", "p2", "p3")

Первый шаг - создать комбинацию всех строк, которые нужно сравнить:

rowIndices <- t(combn(nrow(x), 2))
> rowIndices
     [,1] [,2]
[1,]    1    2
[2,]    1    3
[3,]    2    3

Тогда мы можем использовать эту информацию в apply с length() и intersect(), чтобы получить то, что вы хотите. Обратите внимание, что я также проиндексировал атрибут row.names() data.frame x, чтобы получить имена строк, которые вы хотели.

data.frame(row1 = row.names(x)[rowIndices[, 1]], 
      row2 = row.names(x)[rowIndices[, 2]],
      overlap = apply(rowIndices, 1, function(y) length(intersect(x[y[1] ,], x[y[2] ,])))
      )

Дает вам что-то вроде:

  row1 row2 overlap
1   p1   p2       2
2   p1   p3       1
3   p2   p3       3
2 голосов
/ 03 сентября 2011

Чтение данных примера.

txt <- "P1 A,B,C
        P2 B,C,D,F
        P3 C,D,E,F"
tc <- textConnection(txt)
dat <- read.table(tc,as.is=TRUE)
close(tc)

Преобразование в длинный формат и использование самостоятельного объединения с функцией агрегирования.

dat_split <- strsplit(dat$V2,",")
dat_long <- do.call(rbind,lapply(seq_along(dat_split),
            function(x) data.frame(id=x,x=dat_split[[x]], stringsAsFactors=FALSE)))

result <- sqldf("SELECT t1.id AS id1,t2.id AS id2,count(t1.x) AS N 
                 FROM dat_long AS t1  INNER JOIN dat_long AS t2 
                 WHERE (t2.id>t1.id) AND (t1.x=t2.x) GROUP BY t1.id,t2.id")

Результаты

> result
  id1 id2 N
1   1   2 2
2   1   3 1
3   2   3 3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...