Извлечь нижнюю треугольную часть матрицы - PullRequest
0 голосов
/ 02 июня 2018

Мне было интересно, есть ли в Джулии команда или пакет, который позволяет нам напрямую извлекать нижнюю часть треугольника матрицы, исключая диагональ.Я могу вызвать R команды для этого (например, lowerTriangle пакета gdata), но я хотел бы знать, есть ли у Джулии нечто подобное.Например, представьте, что у меня есть матрица

1.0    0.751   0.734    
0.751   1.0    0.948    
0.734  0.948    1.0

. Я не хочу создавать нижнюю треугольную матрицу, такую ​​как

NA     NA      NA     
0.751   NA      NA    
0.734  0.948    NA

, но извлекать нижнюю часть матрицы в виде массива:0.751 0.734 0.948

Ответы [ 2 ]

0 голосов
/ 03 июня 2018

Использование пониманий :

julia> [M[m, n] for m in 2:size(M, 1) for n in 1:m-1]
3-element Array{Float64,1}:
 0.751
 0.734
 0.948

Но это намного медленнее , чем решение "Сундар / Мэтт Б.":

lower_triangular_1(M) = [M[m, n] for m in 2:size(M, 1) for n in 1:m-1]
lower_triangular_2(M) = [M[m, n] for n in 1:size(M, 2) for m in n+1:size(M, 1)]
lower_triangular_3(M) = M[tril!(trues(size(M)), -1)]
using BenchmarkTools
using LinearAlgebra  # avoid warning in 0.7

M=rand(100, 100)

Тестирование с Джулией Версия 0.7.0-alpha.0:

julia> @btime lower_triangular_1(M);
  73.179 μs (10115 allocations: 444.34 KiB)

julia> @btime lower_triangular_2(M);
  71.157 μs (10117 allocations: 444.41 KiB)

julia> @btime lower_triangular_3(M);
  16.325 μs (6 allocations: 40.19 KiB)

Не элегантно, но быстрее (с @views):

function lower_triangular_4(M)
    # works only for square matrices
    res = similar(M, ((size(M, 1)-1) * size(M, 2)) ÷ 2)
    start_idx = 1
    for n = 1:size(M, 2)-1
        @views column = M[n+1:end, n]
        last_idx = start_idx -1 + length(column)
        @views res[start_idx:last_idx] = column[:]
        start_idx = last_idx + 1
    end
end

julia> @btime lower_triangular_4(M);
  4.272 μs (101 allocations: 44.95 KiB)
0 голосов
/ 02 июня 2018

Если вы согласны с созданием нижней треугольной матрицы в качестве промежуточного шага, вы можете использовать логическое индексирование и tril! с дополнительным аргументом, чтобы получить то, что вам нужно.

julia> M = [1.0 0.751 0.734
0.751 1.0 0.948
0.734 0.948 1.0];
julia> v = M[tril!(trues(size(M)), -1)]
3-element Array{Float64, 1}:
0.751
0.734
0.948

Вызов trues возвращает массив формы М, заполненный логическими значениями true.tril! затем сокращает это до той части матрицы, которую мы хотим.Второй аргумент для трил!говорит ему, с какой супердиагональности начинать, что мы используем здесь, чтобы избежать значений в ведущей диагонали.

Мы используем результат этого для индексации в M, и это возвращает массив с необходимыми значениями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...