Представление трех переменных в трехмерном графике - PullRequest
3 голосов
/ 20 июля 2011

У меня проблема с графиком 3-го измерения для трех переменных.

У меня есть три матрицы: температура, влажность и мощность.В течение одного года, каждый час, каждый из вышеперечисленных были измерены.Итак, мы имеем для каждой матрицы 365 * 24 = 8760 баллов.Затем один средний балл берется каждый день.Итак,

Tavg = 365 X 1
Havg = 365 X 1
Pavg = 365 X 1

В электрической точке Вейв мощность зависит от температуры и влажности.Я хочу обнаружить это отношение с помощью трехмерного графика.

Я пытался использовать mesh, meshz, surf, plot3 и многие другие команды в MATLAB, но, к сожалению, я не смог получить то, что хотел.Например, давайте возьмем первые 10 дней.Здесь каждый день представлен средней температурой, средней влажностью и средней мощностью.

Tavg = [18.6275
   17.7386
   15.4330
   15.4404
   16.4487
   17.4735
   19.4582
   20.6670
   19.8246
   16.4810];

Havg = [75.7105
   65.0892
   40.7025
   45.5119
   47.9225
   62.8814
   48.1127
   62.1248
   73.0119
   60.4168];

Pavg = [13.0921
   13.7083
   13.4703
   13.7500
   13.7023
   10.6311
   13.5000
   12.6250
   13.7083
   12.9286];

Как мне представить эти матрицы на трехмерном графике?

Ответы [ 5 ]

1 голос
/ 23 февраля 2012

Сложность заключается в том, что трехмерные функции построения поверхности (сетка, серфинг и т. Д.) Ищут двумерную матрицу значений z. Таким образом, чтобы использовать их, вам нужно построить такую ​​матрицу из данных.

В настоящее время данные представляют собой море точек в трехмерном пространстве, поэтому вы должны отобразить эти точки на поверхности. Простой подход к этому состоит в том, чтобы разделить плоскость X-Y (температура-влажность) на ячейки и затем взять среднее значение всех данных Z (мощность). Вот некоторый пример кода для этого, который использует accumarray () для вычисления средних значений для каждого бина: % Укажите размеры корзины Tbin = 3; Hbin = 20;

% Create binned average array
% First create a two column array of bin indexes to use as subscripts
subs = [round(Havg/Hbin)+1, round(Tavg/Tbin)+1];

% Now create the Z (power) estimate as the average value in each bin
Pest = accumarray(subs,Pavg,[],@mean);

% And the corresponding X (temp) & Y (humidity) vectors
Tval = Tbin/2:Tbin:size(Pest,2)*Tbin;
Hval = Hbin/2:Hbin:size(Pest,1)*Hbin;

% And create the plot
figure(1)
surf(Tval, Hval, Pest)
xlabel('Temperature')
ylabel('Humidity')
zlabel('Power')
title('Simple binned average')

xlim([14 24])
ylim([40 80])

График немного грубоват (пока не могу опубликовать изображение, так как я новичок), потому что у нас всего несколько точек данных. Мы можем улучшить визуализацию, удалив пустые корзины, установив для них значение NaN. Кроме того, подход биннинга скрывает любые изменения в данных Z (мощности), поэтому мы также можем наложить облако точек ординала, используя plot3, без рисования соединительных линий. (Опять нет изображения б / к я новенький)

Дополнительный код для финального участка: %% Расширенный участок

% Remove zeros (useful with enough valid data)
%Pest(Pest == 0) = NaN;

% First the original points
figure(2)
plot3(Tavg, Havg, Pavg, '.')

hold on
% And now our estimate
% The use of 'FaceColor' 'Interp' uses colors that "bleed" down the face
% rather than only coloring the faces away from the origin
surfc(Tval, Hval, Pest, 'FaceColor', 'Interp')

% Make this plot semi-transparent to see the original dots anb back side
alpha(0.5)

xlabel('Temperature')
ylabel('Humidity')
zlabel('Power')
grid on

title('Nicer binned average')
xlim([14 24])
ylim([40 80])
0 голосов
/ 04 ноября 2014

Ниже ваше решение:

  1. Сохранение / запись функции Myplot3D

    function [x,y,V]=Myplot3D(X,Y,Z)
    x=linspace(X(1),X(end),100);
    y=linspace(Y(1),Y(end),100);
    [Xt,Yt]=meshgrid(x,y);
    V=griddata(X,Y,Z,Xt,Yt);
    
  2. Вызовите следующее из командной строки (или сценария)

    [Tavg_new,Pavg_new,V]=Myplot3D(Tavg,Pavg,Havg);
    surf(Tavg_new,Pavg_new,V)
    colormap jet;
    xlabel('Temperature')
    ylabel('Power/Pressure')
    zlabel('Humidity')
    

surface from 3 vectors

0 голосов
/ 25 февраля 2012

Вы также можете попробовать инструмент GridFit от John D'Errico из MATLAB Central.Этот инструмент создает поверхность, аналогичную интерполяции между точками данных (как это делается с помощью griddata в MATLAB), но с более чистыми результатами, поскольку он сглаживает результирующую поверхность.Концептуально несколько точек данных для близлежащих или перекрывающихся координат X, Y усредняются для получения плавного результата, а не шумных «волнений».Инструмент также допускает некоторую экстраполяцию за пределы точек данных.Вот пример кода (при условии, что инструмент GridFit уже установлен):

%Establish points for surface
num_points = 20;
Tval = linspace(min(Tavg),max(Tavg),num_points);
Hval = linspace(min(Havg),max(Havg),num_points);

%Do the fancy fitting with smoothing
Pest = gridfit(Tavg, Havg, Pavg, Tval, Hval);

%Plot results
figure(5)
surfc(XI,YI,Pest, 'FaceColor', 'Interp')

Чтобы создать еще более приятный график, вы можете добавить метки, некоторую прозрачность и наложить исходные точки:

alpha(0.5)
hold on
plot3(Tavg,Havg,Pavg,'.')

xlabel('Temperature')
ylabel('Humidity')
zlabel('Power')
grid on

title('GridFit')

PS: @upperBound: Спасибо за подсказку по триангуляции Делоне.Это похоже на путь, если вы хотите пройти через каждый из пунктов.Я новичок, поэтому пока не могу комментировать.

0 голосов
/ 23 февраля 2012

Возможно, вы захотите взглянуть на триангуляцию Делоне:

tri = delaunay(Tavg, Havg);
trisurf(tri, Tavg, Havg, Pavg);

Используя ваш пример данных, этот код генерирует интересную «поверхность».Но я считаю, что это еще один способ делать то, что вы хотите.

0 голосов
/ 20 июля 2011

Я думаю, вы запрашиваете поверхностную посадку для ваших данных.Набор инструментов для подгонки кривой отлично справляется с этим:

% Fit model to data.
ft = fittype( 'poly11' );
fitresult = fit( [Tavg, Havg], Pavg, ft);

% Plot fit with data.
plot( fitresult, [xData, yData], zData );
legend( 'fit 1', 'Pavg vs. Tavg, Havg', 'Location', 'NorthEast' );
xlabel( 'Tavg' );
ylabel( 'Havg' );
zlabel( 'Pavg' );
grid on

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

% Find the coefficients.
const = ones(size(Tavg));
coeff = [Tavg Havg const] \ Pavg; 

% Plot the original data points
clf
plot3(Tavg,Havg,Pavg,'r.','MarkerSize',20);
hold on

% Plot the surface.
[xx, yy] = meshgrid( ...
    linspace(min(Tavg),max(Tavg)) , ...
    linspace(min(Havg),max(Havg)) ); 
zz = coeff(1) * xx + coeff(2) * yy + coeff(3);
surf(xx,yy,zz)
title(sprintf('z=(%f)*x+(%f)*y+(%f)',coeff))
grid on
axis tight

Оба они соответствуют линейномуполиномиальная поверхность, т.е. плоскость, но вы, вероятно, захотите использовать что-то более сложное.Оба эти метода могут быть адаптированы к этой ситуации.Более подробную информацию по этому вопросу можно найти на сайте mathworks.com: Как определить уравнение для линии, плоскости или ND с наилучшей посадкой, используя MATLAB? .

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