2011-01-25 4 views
1

У меня квадратная матрица 75 x 75. Все значения в нем, кроме меток, являются десятичными. Я хочу получить все пары меток, имеющих значения выше или ниже установленного мною среза. Скажем, у меня есть следующиеСортировка квадратной матрицы

 A  B  C  D 
A 1  0.2 0.43 0.16 
B 0.2 1  0.86 0.28 
C 0.43 0.86 1  0.76 
D 0.16 0.28 0.76 1 

Я хочу

B C 0.86 
C D 0.76 
A C 0.43 

Как я могу это сделать (без получения дубликатов)?

Благодаря

+0

Вас интересует сортировка или обрезка? – Aaron

ответ

3

Сначала вам нужно преобразовать в представление с одной строкой для каждого значения; одним из способов сделать это является преобразование в матрицу, а затем в data.frame. Чтобы избежать дублирования, установите нижний треугольник (возможно, включая диагональ) в NA перед преобразованием в кадр данных, а затем возьмите подмножество фрейма данных, где значения не являются NA.

mtx <- matrix(rnorm(16), 4, 4, dimnames = list(LETTERS[1:4], LETTERS[1:4])) 
mtx[lower.tri(mtx, diag=TRUE)] <- NA 
dx <- as.data.frame(as.table(mtx)) 
dx <- subset(dx, !is.na(Freq)) 

Затем вы можете взять подмножество по желанию из результирующего фрейма данных.

> subset(dx, Freq>0) 
    Var1 Var2  Freq 
5  A B 1.9564158 
9  A C 1.7188939 
14 B D 0.1848542 
2

Один из способов заключается в использовании melt Fn из reshape пакета (ОБНОВЛЕНО во избежание дублирования в симметричных матриц, и сортировки конечного результата).

> mtx <- matrix(round(10*rnorm(16)), 
       4, 4, dimnames = list(LETTERS[1:4], LETTERS[1:4])) 
> mtx[ upper.tri(mtx)] <- NA 
> mtx 
    A B C D 
A -7 NA NA NA 
B 23 17 NA NA 
C 6 -2 20 NA 
D -23 8 15 -6 
> require(reshape) 
> df <- cbind(data.frame(Row = rownames(mtx)), as.data.frame(mtx)) 
> df.m <- melt(df, id = 'Row', variable_name = 'Col') 
> df.m 
    Row Col value 
1 A A -7 
2 B A 23 
3 C A  6 
4 D A -23 
5 A B NA 
6 B B 17 
7 C B -2 
8 D B  8 
9 A C NA 
10 B C NA 
11 C C 20 
12 D C 15 
13 A D NA 
14 B D NA 
15 C D NA 
16 D D -6 
> filt <- subset(df.m, value < 0) 
> filt[order(filt$value),] 
    Row Col value 
4 D A -23 
1 A A -7 
16 D D -6 
7 C B -2 

Конечно, вы можете отформатировать результат любым способом, например.

> cat(with(filt, paste(Row, Col, value, '\n'))) 
A A -7 
D A -23 
C B -2 
D D -6 
+0

Это не избавит вас от дубликатов (если мы имеем дело с симметричным, как пример из OP). Как это сделать, остается как упражнение. :) –

+0

Большое спасибо. Но как удалить дубликаты. Например, «A-B» и «B-A». Также как я сортирую это подмножество, в порядке убывания, поддерживая пару Row Col? – y2p

+0

PLS см. Мое обновление –

0
library(fBasics) 
Z <- Triang(X) 
data.frame(t(apply(which(Z >= 0.43 & Z < 1 ,arr.ind = T),1, 
    function(y) c(rownames(Z)[y[1]],colnames(Z)[y[2]],Z[y[1],y[2]])))) 

дает

X1 X2 X3 
A A C 0.43 
B B C 0.86 
C C D 0.76 
0

С матрицей и отсечение

m <- matrix(rnorm(16), 4, 4, dimnames = list(LETTERS[1:4], LETTERS[1:4])) 
cut <- 0 

индекс значения, удовлетворяющие указанным критериям и использовать, чтобы извлечь нужные значения и имена строк. Сортировка после факта

i <- lower.tri(m, diag=TRUE) * m > cut 
df <- data.frame(Row=rownames(m)[row(m)[i]], Col=colnames(m)[col(m)[i]], 
       Val=m[i]) 
df[order(df$Val),]