Как правильно выбрать строки из матрицы с помощью логического массива? - PullRequest
2 голосов
/ 22 апреля 2019

У меня есть логический массив (из предыдущих вычислений), и я хотел бы выбрать связанные строки из нескольких матриц.Вот почему мне нужен правильный индексный массив (для повторного использования позже).Это легко сделать в Matlab и Python, но я не использую правильный юлианский способ сделать это ...

Я знаю о DataFrames, но хотел бы найти ортодоксальную матрицу и массив для этого.

В Matlab я бы сказал:

n= 9; temp= 1:n; A= 1.0 + temp;
someTest= mod(temp,2) == 0; % just a substitute of a more complex case

% now I have both someTest and A!
inds= find(someTest); Anew= A(inds,:); 
% I got inds (which I need)!

Я получил работу так:

n= 10; data= Array(1:n); A= 1.0 .+ data;
someTest= rem.(data,2) .== 0;

inds= [xy[2] for xy in zip(someTest,1:length(someTest)) if xy[1]]; # (*)
Anew= A[inds,:];

Я предположил, что существует более короткий способ выразитьвышеуказанная фраза.в v. 0.6 была функция find (), но я еще не понял смысл документации julia (я очень новичок в этом).

Ответы [ 3 ]

2 голосов
/ 22 апреля 2019

Вы можете использовать BitArray просто для выбора элементов:

julia> A[someTest]
5-element Array{Float64,1}:
  3.0
  5.0
  7.0
  9.0
 11.0

В вашем случае:

julia> A[someTest,:] == A[inds,:]
true
1 голос
/ 22 апреля 2019

find в 0.6 был переименован в findall в Julia 1.0.

Чтобы получить inds, вы можете просто сделать следующее:

inds = findall(someTest)

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

inds = findall(x -> rem(x,2) == 0, data)

Возвращает индексы data, для которых предикат rem(x,2) == 0 возвращает true. Это не выделит промежуточный массив для поиска индексов и должен быть быстрее.

Как примечание, в большинстве случаев вам не нужно материализировать диапазон в Джулии. Диапазоны уже повторяемы и индексируются. Они будут автоматически преобразованы в Array, когда возникнет такая необходимость. Array(1:n) или collect(1:n) обычно избыточны и выделяют больше памяти.

0 голосов
/ 23 апреля 2019

Ваш код Matlab не работает. A - это просто вектор-строка (матрица 1x9), поэтому при попытке сделать A(inds, :) вы получите ошибку:

>> Anew= A(inds,:)
Index in position 1 exceeds array bounds
(must not exceed 1).

Но если вы просто исправите это, вы можете решить проблему одинаково в Matlab и Julia, используя либо логические, либо обычные индексы:

Matlab (на этот раз я проверяю, что это матрица):

n = 9;
temp = (1:n).'; 
A = temp * (1:4);
inds = mod(temp,2) == 0;

>> A(inds, :) % using logical indices

ans =

     2     4     6     8
     4     8    12    16
     6    12    18    24
     8    16    24    32

>> A(find(inds), :) % using regular indices

ans =

     2     4     6     8
     4     8    12    16
     6    12    18    24
     8    16    24    32

А теперь, Юля:

n = 9;
temp = 1:n;
A = temp .* (1:4)'; # notice that we're transposing the opposite vector from Matlab
inds = mod.(temp, 2) .== 0;  # you can use iseven.(temp) instead

julia> A[inds, :]  # logical indices (BitArray)
4×4 Array{Int64,2}:
 2   4   6   8
 4   8  12  16
 6  12  18  24
 8  16  24  32

julia> A[findall(inds), :]  # regular integer indices
4×4 Array{Int64,2}:
 2   4   6   8
 4   8  12  16
 6  12  18  24
 8  16  24  32

В этом случае я бы использовал логические индексы как у Джулии, так и у Матлаба. Фактически, линтер Matlab (в редакторе) скажет, что вы должны использовать здесь логические индексы, потому что это быстрее. Однако в Джулии могут быть случаи, когда более эффективно использовать inds = findall(iseven, temp) и просто пропустить логический BitArray, как говорит @hckr.

...