создать оценочную матрицу из двух фреймов данных - PullRequest
1 голос
/ 06 января 2012

Я пытаюсь сравнить наборы переменных (X), которые хранятся в двух фреймах данных (foo, bar). Каждый X является уникальной независимой переменной, с которой связано до 10 значений Y. Я хотел бы сравнить каждый foo.X с каждым bar.X, сравнивая количество общих значений Y, которые у них общие - так что на выходе могла бы быть матрица с осями foo.x длиной bar.x.

этот простой пример foo и bar хотел бы вернуть матрицу 2x2, сравнивая a, b с c, d:

foo <- data.frame(x= c('a', 'a', 'a', 'b', 'b', 'b'), y=c('ab', 'ac', 'ad', 'ae', 'fx', 'fy'))
bar <- data.frame(x= c('c', 'c', 'c', 'd', 'd', 'd'), y=c('ab', 'xy', 'xz', 'xy', 'fx', 'xz'))

EDIT:


Я оставил следующий код для изучения другими новичками (поскольку циклы эффективны, но, вероятно, очень неоптимальны), но два приведенных ниже решения эффективны. В частности, использование Рамнатом data.table очень эффективно при работе с очень большими фреймами данных.

сохраняет кадры данных в виде списков, в которых хранятся значения y с использованием функции stack

foo.list <- dlply(foo, .(x), function(x) stack(x, select = y))
bar.list <- dlply(bar, .(x),function(x)  stack(x, select = y))

написать функцию для сравнения членства в двух составных списках

comparelists <- function(list1, list2) {
  for (i in list1){ 
    for (j in list2){
      count <- 0
      if (i[[1]] %in% j[[1]]) count <- count + 1
    }
  }
  return count
  }

написать выходную матрицу

output.matrix <- matrix(1:length(foo.list), 1:length(bar.list))
for (i in foo.list){
  for (j in bar.list){
    output.matrix[i,j] <- comparelists(i,j)

    }

}

Ответы [ 2 ]

4 голосов
/ 06 января 2012

Там должно быть сто способов сделать это;вот тот, который кажется мне относительно простым:

library(reshape2)
foo <- data.frame(x = c('a', 'a', 'a', 'b', 'b', 'b'), 
                  y = c('ab', 'ac', 'ad', 'ae', 'fx', 'fy'))
bar <- data.frame(x = c('c', 'c', 'c', 'd', 'd', 'd'), 
                  y = c('ab', 'xy', 'xz', 'xy', 'fx', 'xz'))

# Create a function that counts the number of common elements in two groups
nShared <- function(A, B) {
    length(intersect(with(foo, y[x==A]), with(bar, y[x==B])))
}

# Enumerate all combinations of groups in foo and bar
(combos <- expand.grid(foo.x=unique(foo$x), bar.x=unique(bar$x)))
#   foo.x bar.x
# 1     a     c
# 2     b     c
# 3     a     d
# 4     b     d

# Find number of elements in common among all pairs of groups
combos$n <- mapply(nShared, A=combos$foo.x, B=combos$bar.x)

# Reshape results into matrix form
dcast(combos, foo.x ~ bar.x)
#   foo.x c d
# 1     a 1 0
# 2     b 0 1
3 голосов
/ 07 января 2012

Вот более простой подход с использованием merge

library(reshape2)
df1 <- merge(foo, bar, by = 'y')
dcast(df1, x.x ~ x.y, length)

  x.x c d
1   a 1 0
2   b 0 1

EDIT. Слияние может быть быстрее, используя data.table. Вот код

foo_dt <- data.table(foo, key = 'y')
bar_dt <- data.table(bar, key = 'y')
df1 <- bar_dt[foo_dt, nomatch = 0]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...