2015-11-21 2 views
3

У меня есть матрица, первый столбец которой содержит идентификаторы пользователей, а второй столбец содержит 1 и 0. Мне нужно узнать 10 лучших идентификаторов пользователей с наибольшим количеством 1s. То есть, если входная матрица заключается в следующей,Как отсортировать матрицу на основе количества вхождений определенного значения в соответствующем столбце без использования для циклов?

27 0 
36 0 
36 1 
36 0 
36 0 
27 0 
27 0 
36 1 
27 0 
27 0 
27 0 
27 0 
27 1 
36 0 

Я хочу выход быть следующим:

36 2 
27 1 

То есть, даже если 27 происходит в 8 раз и 36 происходят только 6 раз, 36 должен превышать 27, потому что он имеет больше значений 1 в исходной матрице. Как это сделать без использования цикла for, потому что для цикла требуется много времени, а матрица на самом деле довольно большая, с множеством уникальных идентификаторов пользователей.

+0

Какой язык вы используете, и то, что вы пробовали до сих пор? – albert

+0

@albert MATLAB. При отправке вопроса я использовал тег 'matlab'. – Kristada673

+0

Что здесь означает номер 2? – choroba

ответ

2

, что программа установки проблема кажется, идеально подходит для решения с unique & accumarray -

%// Select rows with col-2 as 1s & find unique col-1 elements and IDs 
[unq_sA1,~,id] = unique(A(A(:,2)==1,1)) 

%// Get counts of such unique rows 
counts = accumarray(id(:),1) 

%// Get argsort for the counts to index into unique rows and the counts 
[~,sort_idx] = sort(counts,'descend') 
out = [unq_sA1(sort_idx) counts(sort_idx)] 
+0

Очень приятное решение. Вероятно, также явно быстрее, чем мое решение. – hbaderts

+0

@hbaderts Спасибо! Yeah 'arrayfun' не забавны для производительности AFAIK :) – Divakar

+0

Спасибо тонну! Я принимаю ваше решение как ответ, потому что он решил проблему за 1 секунду. Мой наивный метод, включающий 2 цикла, как я бы сделал на C, занял более 12 часов, а ответ другого джентльмена занял 2 часа, чтобы выполнить эту работу. – Kristada673

2

Вы можете найти все идентификаторы пользователей с функцией unique, которая возвращает все уникальные значения в массиве:

ids = unique(inp(:,1)); 

Количество единиц для идентификатора может рассчитывается

sum(inp(inp(:,1)==ID,2)) 

, который использует некоторые matrix indexing, чтобы найти все строки, в которых первая запись является выбранным идентификатором пользователя ID, и суммирует вторую запись этих строк.

Чтобы сделать эти суммы в векторном формате, вы можете, например, используйте функцию arrayfun, которая применяет функцию к каждому элементу поставляемого массива. Функция, которую вы хотите вызвать, представляет собой сумму, указанную выше, и вы хотите применить ее ко всем уникальным идентификаторам. Это делается

arrayfun(@(x)sum(inp(inp(:,1)==x,2)),ids) 

ans = 
    1 
    2 
+0

Когда я пытаюсь выполнить код, я получаю следующую ошибку: «Индекс превышает размеры матрицы». Кроме того, не совсем понятно, как использовать ваш код. Поэтому я запустил 'arrayfun' внутри цикла for, для x = 1: size (ids (:, 1), 1)'. Даже тогда ошибка сохраняется. – Kristada673

+0

Нет необходимости в цикле: 'arrayfun' применяет функцию к каждому значению в' ids'. Просто запустите первую строку 'ids = ...' (и, возможно, проверьте, правильно ли это), а затем вызовите строку 'arrayfun (...)'. – hbaderts

+0

Это работает, но когда я применяю его на моей фактической матрице, это не сокращает время. С 2 для циклов мне потребовалось больше 12 часов, чтобы выполнить эту работу. И с вашим решением его уже было больше часа. Я надеюсь, что это займет не больше 10 часов, потому что тогда его производительность будет эквивалентна 2 циклам. – Kristada673

Смежные вопросы