Создание треугольной матрицы
Там должен быть элегантный способ сделать это, но я не могу понять так:
Колонки - это вероятности от 1 до 0, идущие вправо
Строки - это вероятности от 0 до 1, идущие вниз
Этот код kludgy дает желаемый результат (но я хочу сделать это с гораздо большей матрицей, чем это):
# Vector entries are rowname - colname, if >= 0
#
rb0 <- c(NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, 0)
rb1 <- c(NA,NA,NA,NA,NA,NA,NA,NA,NA, 0,.1)
rb2 <- c(NA,NA,NA,NA,NA,NA,NA,NA, 0,.1,.2)
rb3 <- c(NA,NA,NA,NA,NA,NA,NA, 0,.1,.2,.3)
rb4 <- c(NA,NA,NA,NA,NA,NA, 0,.1,.2,.3,.4)
rb5 <- c(NA,NA,NA,NA,NA, 0,.1,.2,.3,.4,.5)
rb6 <- c(NA,NA,NA,NA, 0,.1,.2,.3,.4,.5,.6)
rb7 <- c(NA,NA,NA, 0,.1,.2,.3,.4,.5,.6,.7)
rb8 <- c(NA,NA, 0,.1,.2,.3,.4,.5,.6,.7,.8)
rb9 <- c(NA, 0,.1,.2,.3,.4,.5,.6,.7,.8,.9)
rb10 <- c( 0,.1,.2,.3,.4,.5,.6,.7,.8,.9,1 )
indbias <- rbind(rb0,rb1,rb2,rb3,rb4,rb5,rb6,rb7,rb8,rb9,rb10)
colnames(indbias) <- seq(1,0,by=-.1)
rownames(indbias) <- seq(0,1,by=.1)
indbias
Спасибо!
Ответы
Ответ 1
mat <- matrix(NA, 10,10)
mat[row(mat)+col(mat) >=11] <- (row(mat)+col(mat) -11)[row(mat)+col(mat)>=11]/10
mat
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] NA NA NA NA NA NA NA NA NA 0.0
[2,] NA NA NA NA NA NA NA NA 0.0 0.1
[3,] NA NA NA NA NA NA NA 0.0 0.1 0.2
[4,] NA NA NA NA NA NA 0.0 0.1 0.2 0.3
[5,] NA NA NA NA NA 0.0 0.1 0.2 0.3 0.4
[6,] NA NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5
[7,] NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6
[8,] NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7
[9,] NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8
[10,] 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
Я думаю, что это будет намного быстрее, чем решение plyr, и мне кажется, что это легче понять. Он в основном устанавливает тест для записей, находящихся в нижнем правом "треугольнике", а затем делит результаты этой "тестовой" матрицы bu 10. Вы можете посмотреть тестовую матрицу с помощью этого кода:
row(mat)+col(mat) -11
Изменить: я подумал, что возможно сделать матрицу один раз, как показано на примере себастьяна-с, а затем выполнить один тест, чтобы выполнить настройку NA, может быть быстрее (с одной трети количество вызовов row
и col
) но, по-видимому, она составляет лишь одну треть. Похоже, что два вызова seq занимают больше времени, чем дополнительные:
mat <- round(outer(seq(-0.5, 0.5, 0.1), seq(-0.5, 0.5, 0.1), `+`), 1)
is.na(mat) <- row(mat)+col(mat) <= 11
mat
Я нашел другое решение, основанное на малоизвестной функции embed
:
mat <- embed(seq(-1,1, by=0.1), 11 )[,11:1]
is.na(mat) <- row(mat)+col(mat) <= 11
Хотя это на 50% быстрее, чем новое решение, оно все же медленнее оригинала.
Ответ 2
Несколько другое решение, близкое по стилю к @DWin's:
Создайте матрицу с соответствующим нижним треугольником (я не думаю, что округление строго необходимо, но в противном случае ошибка с плавающей запятой заставляет его выглядеть ужасно):
mat <- round(outer(seq(-0.5, 0.5, 0.1), seq(-0.5, 0.5, 0.1), `+`), 1)
mat
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
[1,] -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0
[2,] -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1
[3,] -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2
[4,] -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3
[5,] -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4
[6,] -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5
[7,] -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6
[8,] -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7
[9,] -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8
[10,] -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
[11,] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Переверните столбцы
mat <- mat[,rev(seq.int(ncol(mat)))]
Снимите верхний треугольник:
mat[upper.tri(mat)] <- NA
Переверните столбцы:
mat <- mat[,rev(seq_len(ncol(mat)))]
mat
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
[1,] NA NA NA NA NA NA NA NA NA NA 0.0
[2,] NA NA NA NA NA NA NA NA NA 0.0 0.1
[3,] NA NA NA NA NA NA NA NA 0.0 0.1 0.2
[4,] NA NA NA NA NA NA NA 0.0 0.1 0.2 0.3
[5,] NA NA NA NA NA NA 0.0 0.1 0.2 0.3 0.4
[6,] NA NA NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5
[7,] NA NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6
[8,] NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7
[9,] NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8
[10,] NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
[11,] 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Вы можете изменить там имена ростов.
EDIT: Учитывая, что существует так много решений, вам может быть интересно посмотреть, как они сравниваются. Используя microbenchmark
:
Unit: microseconds
expr min lq median uq max
1 AGS() 682.491 738.9370 838.0955 892.8815 4518.740
2 DW() 23.244 27.1680 31.3930 34.8650 70.937
3 MvG() 15469.664 15920.4820 17352.3215 17827.4380 18989.270
4 SC() 118.629 131.4575 144.1360 157.7190 631.779
@DWin-решение кажется самым быстрым на вполне допустимом уровне.
Ответ 3
Один из возможных способов, используя мою текущую любимую библиотеку:
library(plyr)
daply(expand.grid(x=seq(1,0,-.1), y=seq(0,1,.1)),
.(y, x), with,
if (x+y >= 1) x+y-1 else NA)
Это дает следующий результат:
x
y 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
0 NA NA NA NA NA NA NA NA NA NA 0.0
0.1 NA NA NA NA NA NA NA NA NA 0.0 0.1
0.2 NA NA NA NA NA NA NA NA 0.0 0.1 0.2
0.3 NA NA NA NA NA NA NA 0.0 0.1 0.2 0.3
0.4 NA NA NA NA NA NA 0.0 0.1 0.2 0.3 0.4
0.5 NA NA NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5
0.6 NA NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6
0.7 NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7
0.8 NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8
0.9 NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
1 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Идея состоит в том, что expand.grid
создает фрейм данных всех возможных значений ячеек. Вы могли бы использовать merge
для этого. Затем вы применяете функцию к каждому из этих значений для вычисления содержимого ячейки. И пусть daply
превратит это в красивую матрицу для вас, включая имена.
EDIT:
Хорошо, вы хотели, чтобы столбцы помечены в обратном порядке. ddply
сортирует их по возрастанию. Поэтому попробуйте следующее:
daply(expand.grid(x=seq(0,1,.1), y=seq(0,1,.1)),
.(y, x), with,
if (y-x >= 0) y-x else NA)[,11:1]
x
y 1 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1 0
0 NA NA NA NA NA NA NA NA NA NA 0.0
0.1 NA NA NA NA NA NA NA NA NA 0.0 0.1
0.2 NA NA NA NA NA NA NA NA 0.0 0.1 0.2
0.3 NA NA NA NA NA NA NA 0.0 0.1 0.2 0.3
0.4 NA NA NA NA NA NA 0.0 0.1 0.2 0.3 0.4
0.5 NA NA NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5
0.6 NA NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6
0.7 NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7
0.8 NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8
0.9 NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
1 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Ответ 4
require(matlab)
x=matrix(seq(0,1,.1),1)
X=x[rep(1,c(11)),]
X[upper.tri(X)]=NA
X=t(X)
for(a in 1:11){
X[1:a,a]=rev(X[1:a,a])
}
X=flipud(X)
colnames(X) <- seq(1,0,by=-.1)
rownames(X) <- seq(0,1,by=.1)