2016-08-03 4 views
3

У меня есть набор точек, представленных двумерным вектором (X).Символы графика в зависимости от векторных значений

Каждая точка относится к категориальным данным (Y), представленным целочисленным значением (от 1 до 4).

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

Игрушка пример:

X = randi(100,10,2); % 10 points ranging 1:100 in 2D space 
Y = randi(4,10,1);  % class of the points (1 to 4) 

создать вектор символов для каждого класса:

S = {'bx' 'rx' 'b.' 'r.'}; 

Тогда я стараюсь:

plot(X(:,1), X(:,2), S(Y)) 


Error using plot 
Invalid first data argument 

Как я могу присвоить каждой точке X другой символ, основанный на значении Y?

Проклятие Я могу использовать цикл для каждого класса и строить разные классы по одному. Но есть ли метод прямого построения каждого класса с другим символом?

ответ

4

Нет необходимости для цикла, используйте gscatter:

X = randi(100,10,2); % 10 points ranging 1:100 in 2D space 
Y = randi(4,10,1);  % class of the points (1 to 4) 
color = 'brbr'; 
symbol = 'xx..'; 
gscatter(X(:,1),X(:,2),Y,color,symbol) 

и вы получите: group scatter

+0

Никогда не использовал его раньше, поэтому не думал об этом ... Это, безусловно, лучший ответ! +1 =) –

+0

Это именно то, что я искал. благодаря –

3

Если X имеет много строк, но существует только несколько типов S, тогда я предлагаю вам сначала проверить второй подход. Он оптимизирован для скорости, а не для удобочитаемости. Это примерно в два раза быстрее, если вектор имеет 10 элементов и более чем в 200 раз быстрее, если вектор имеет 1000 элементов.


Первый подход (легко читать):

Независимо от подхода, я думаю, вам нужно петля для этого:

hold on 
arrayfun(@(n) plot(X(n,1), X(n,2), S{Y(n)}), 1:size(X,1)) 

Или, чтобы написать цикл в " Традиционный способ ":

hold on 
for n = 1:size(X,1) 
    plot(X(n,1), X(n,2), S{Y(n)}) 
end 

enter image description here

Второй подход (дает тот же сюжет, что и выше):

Если набор данных велик, вы можете сортировать [Y_sorted, sort_idx] = sort(Y), а затем использовать sort_idx индексировать X, как это: X_sorted = X(sort_idx);. После этого вы разделите X_sorted на 4 группы, по одному для каждого из Y -значений, используя histc и mat2cell. Затем вы переходите по четырем группам и запишите их по отдельности.

Таким образом, вам нужно всего лишь перебрать четыре значения, независимо от количества элементов в ваших данных. Это должно быть намного быстрее, если число элементов велико.

[Y_sorted, Y_index] = sort(Y); 
X_sorted = X(Y_index, :); 
X_cell = mat2cell(X_sorted, histc(Y,1:numel(S))); 

hold on 
for ii = 1:numel(X_cell) 
    plot(X_cell{ii}(:,1),X_cell{ii}(:,2),S{ii}) 
end 

Бенчмаркинг:

Я сделал очень простой сравнительный анализ двух подходов с использованием timeit.Результат показывает, что второй подход намного быстрее:

Для 10 элементов:

First approach: 0.0086 
Second approach: 0.0037 

на 1000 элементов:

First approach = 0.8409 
Second approach = 0.0039 
+0

Спасибо. На самом деле вместо сортировки вы можете просто получить значения X, которые соответствуют классу, обрабатываемому в цикле: 'X (Y == i,:)' вернет точки, принадлежащие классу 'i'. –

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