Создать матрицу из функции и двух числовых фреймов данных - PullRequest
4 голосов
/ 29 марта 2012

Я пытаюсь создать матрицы различных функций расстояния / ассоциации в R. У меня есть функция, похожая на cor, которая дает связь между двумя векторами. Теперь я хочу взять фрейм данных (или матрицу) числовых векторов, например, mtcars, и создать матрицу из функции и фрейма данных. Я думал, что это то, для чего outer, но я не получаю его на работу. Вот попытка использования cor и mtcars.

cor(mtcars$mpg, mtcars$cyl)  #a function that gives an association between two vectors                  
outer(mtcars, mtcars, "cor") #the attempt to create a matrix of all vectors in a df

Да, я знаю, что cor может сделать это напрямую, давайте представим, что это невозможно. что cor просто находит корреляции между двумя векторами.

Таким образом, конечной целью будет получить матрицу, полученную из cor(mtcars).

Заранее спасибо.

Ответы [ 2 ]

8 голосов
/ 29 марта 2012

Вы можете использовать outer с функцией, которая принимает имена столбцов или номера столбцов в качестве аргументов.

outer(
  names(mtcars), 
  names(mtcars), 
  Vectorize(function(i,j) cor(mtcars[,i],mtcars[,j]))
)
3 голосов
/ 29 марта 2012

outer не напрямую зависит от работы.Он просто расширит свои X и Y векторы и вызовет cor один раз. РЕДАКТИРОВАТЬ Как показывает @Vincent Zoonekynd, вы можете адаптировать его к работе.

В противном случае довольно простой цикл делает свое дело:

m <- as.matrix(mtcars)
r <- matrix(1, ncol(m), ncol(m), dimnames=list(colnames(m), colnames(m)))
for(i in 1:(ncol(m)-1)) {
  for(j in (i+1):ncol(m)) {
     r[i,j] <- cor(m[,i], m[,j])
     r[j,i] <- r[i,j]
  }
}

all.equal(r, cor(m)) # Sanity check...

r # print resulting 11x11 correlation matrix

... Вот яПредположим, что ваша корреляция симметрична, и cor (x, x) == 1.

ОБНОВЛЕНИЕ Поскольку решение Винсента гораздо более элегантно, мне приходится противостоять тому факту, что мое решениеВ 2 раза быстрее: -)

# Huge data frame (1e6 rows, 10 cols)
d <- data.frame(matrix(1:1e7, ncol=10))

# Vincent's solution    
system.time(outer(
  names(d), 
  names(d), 
  r <- Vectorize(function(i,j) cor(d[,i],d[,j]))
)) # 2.25 secs

# My solution    
system.time({
m <- d
r <- matrix(1, ncol(m), ncol(m), dimnames=list(colnames(m), colnames(m)))
for(i in 1:(ncol(m)-1)) {
  for(j in (i+1):ncol(m)) {
     r[i,j] <- cor(m[,i], m[,j])
     r[j,i] <- r[i,j]
  }
}
}) # 1.0 secs
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...