2016-09-06 7 views
0

У меня есть массив ячеек [5x1], которые все ячейки являются векторы-столбцы, такие как:Извлечение данных из ячейки массива с помощью вектора и преобразование в массив

exInt = 

    [46x1 double] 
    [54x1 double] 
    [40x1 double] 
    [51x1 double] 
    [ 9x1 double] 

мне нужно иметь вектор (VEC) содержащий ячейки в extInt Мне нужно извлечь, а затем я должен преобразовать их в один массив столбцов. Такие как:

vec = [1,3]; 
    Output = cell2mat(extInt{vec}) 

Выход должен стать чем-то вроде массива [86x1 double].

Я так закодировали я получаю:

Error using cell2mat 
Too many input arguments. 

Если возможно, я хотел бы иметь решение не используя цикл.

+0

В чем вопрос? Не работает этот код? Если нет, укажите, почему нет. – Adriaan

+0

Прошу прощения, я отредактировал вопрос. –

+0

Попробуйте ['cellfun'] (http://mathworks.com/help/matlab/ref/cellfun.html) – Adriaan

ответ

4

Лучший подход здесь использовать cat вместе с comma-separted list созданной {} индексации с получением целевого вектора-столбца. Мы определяем первое измерение как первый аргумент, так как у вас есть все векторы столбцов, и мы хотим, чтобы результат также был вектором столбца.

out = cat(1, extInt{vec}) 

Учитывая введенные данные, cell2mat попытки CONCATENATE по втором измерении который потерпит неудачу для ваших данных, поскольку все данные имеют разное количество строк. Вот почему (в вашем примере) вам пришлось транспонировать данные до вызова cell2mat.

Update

Вот тест, чтобы сравнить время выполнения между cat и cell2mat подходов.

function benchit() 

    nRows = linspace(10, 1000, 100); 

    [times1, times2] = deal(zeros(size(nRows))); 

    for k = 1:numel(nRows) 

     rows = nRows(k); 

     data = arrayfun(@(x)rand(randi([10, 50], 1), 1), 1:rows, 'uni', 0); 
     vec = 1:2:numel(data); 

     times1(k) = timeit(@()cat_method(data, vec)); 

     data = arrayfun(@(x)rand(randi([10, 50], 1), 1), 1:rows, 'uni', 0); 
     vec = 1:2:numel(data); 

     times2(k) = timeit(@()cell2mat_method(data, vec)); 
    end 

    figure 

    hplot(1) = plot(nRows, times1 * 1000, 'DisplayName', 'cat'); 
    hold on 
    hplot(2) = plot(nRows, times2 * 1000, 'DisplayName', 'cell2mat'); 

    ylabel('Execution Times (ms)') 
    xlabel('# of Cell Array Elements') 

    legend(hplot) 
end 

function out = cat_method(data, vec) 
    out = cat(1, data{vec}); 
end 

function out = cell2mat_method(data, vec) 
    out = cell2mat(data(vec)'); 
end 

enter image description here

Причина постоянной смещения между ними состоит в том, что cell2mat вызовы cat внутренне, но добавляет некоторую дополнительную логику поверх него. Если вы просто используете cat напрямую, вы обойдете эти дополнительные накладные расходы.

3

У вас есть небольшая ошибка в коде

Изменение

Output = cell2mat(extInt{vec}); 

в

Output = cell2mat(extInt(vec)); 

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

  • Используйте фигурные скобки {} для установки или получения содержимого ячейки массивов.
  • Используйте скобки() для индексирования в массив ячеек для сбора подмножества ячеек вместе в другом массиве ячеек.

В вашем примере, используя скобки с индексом вектора vec будет производить 2 отдельных выхода (я сделал более короткую версию extInt ниже)

extInt = {[1],[2 3],[4 5 6]}; 
extInt{vec} 
ans = 
    1 
ans = 
    4  5  6 

Поскольку это 2 отдельные выходы, его также будет 2 отдельных входа для функции cell2mat. Поскольку эта функция принимает только один вход, вы получаете ошибку.

Один вариант в вашем собственном решении. Возьмите два выхода и поместить их в новых (безымянных) клетках

{extInt{vec}} 
ans = 
    [1] [1x3 double] 

Теперь этот (единственный) результат идет в cell2mat без проблем. (Обратите внимание, что вам может потребоваться перенести результат в зависимости от того, есть ли у вас векторы столбцов или строк в вашей ячейке. Размерный вектор (или матрица) для объединения необходимо согласовать/выровнять.)

Другой способ используйте круглые скобки (как указано выше в моем решении). Здесь подмножество исходной ячейки возвращается. Поэтому он переходит непосредственно в функцию cell2mat.

extInt(vec) 
ans = 
    [1] [1x3 double] 
+0

это тоже работает. Я думал, что массивы ячеек могут использовать только {} –

+1

@ArturCastiel' {} 'возвращает * содержимое * элементов массива ячеек и '()' возвращает подмножество массива ячеек в качестве массива ячеек. – Suever

+0

. Действительно, я обновлю свой ответ с дополнительной информацией. – NLindros

0

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

Output = cell2mat({extInt{vec}}') 
+1

Я добавил контрольный показатель для своего ответа, используя вместо этого 'cat' из 'cell2mat' для сравнения производительности. – Suever

0

использование

Output = cell2mat(extInt(vec)) 

Поскольку вы хотите обращаться к ячейкам в extInt, а не о содержании ячеек

extInt(vec) 
extInt{vec} 

попробовать те, чтобы увидеть, что происходит на

+1

Почему вы дали тот же ответ, что и [nilZ0r] (http://stackoverflow.com/a/39348928/5211833) через четыре минуты? И это без каких-либо усилий, чтобы объяснить, почему это происходит. – Adriaan

+1

@Adriaan, как вы сказали, это было всего 4 минуты **. Это довольно короткое время, чтобы ожидать совпадения ответов. Зачем ты спрашиваешь кого-нибудь об этом? – erfan