我在处理三个变量的第三维图时遇到问题。
我有三个矩阵:温度,湿度和功率。在一年中,每小时,测量上述每一个。因此,我们为每个矩阵365 * 24 = 8760点。然后,每天采取一个平均点。所以,
Tavg = 365 X 1
Havg = 365 X 1
Pavg = 365 X 1
在电气观点上,功率取决于温度和湿度。我想用三维图发现这种关系。
我尝试在MATLAB中使用mesh,meshz,surf,plot3和许多其他命令但不幸的是我无法得到我想要的东西。例如,让我们前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];
我如何通过三维图表来表示这些矩阵?
答案 0 :(得分:1)
挑战在于三维表面绘图功能(网格,冲浪等)正在寻找z值的二维矩阵。因此,要使用它们,您需要根据数据构建这样的矩阵。
目前,数据是三维空间中的点海,因此,您必须将这些点映射到曲面。一种简单的方法是将X-Y(温度 - 湿度)平面分成箱,然后取所有Z(功率)数据的平均值。下面是一些示例代码,它使用accumarray()来计算每个bin的平均值: %指定箱尺寸 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覆盖区域点云,而无需绘制连接线。 (再没有图像b / c我是新的)
最终情节的附加代码: %%扩展图
% 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])
答案 1 :(得分:0)
我认为您要求表面适合您的数据。曲线拟合工具箱处理得很好:
% 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:How can I determine the equation of the best-fit line, plane, or N-D surface using MATLAB?。
答案 2 :(得分:0)
你可能想看看Delaunay三角测量:
tri = delaunay(Tavg, Havg);
trisurf(tri, Tavg, Havg, Pavg);
使用您的示例数据,此代码会生成一个有趣的“表面”。但我相信这是做你想做的另一种方式。
答案 3 :(得分:0)
您也可以尝试使用MATLAB Central的John D'Errico的GridFit工具。该工具生成的表面类似于数据点之间的插值(由MATLAB的griddata完成),但结果更清晰,因为它可以平滑生成的曲面。概念上,对于附近或重叠的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:感谢Delaunay三角测量技巧。如果你想要了解每一点,这似乎是要走的路。我是新手,所以无法发表评论。
答案 4 :(得分:0)
以下是您的解决方案:
保存/写入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);
从命令行(或脚本)中调用以下内容
[Tavg_new,Pavg_new,V]=Myplot3D(Tavg,Pavg,Havg);
surf(Tavg_new,Pavg_new,V)
colormap jet;
xlabel('Temperature')
ylabel('Power/Pressure')
zlabel('Humidity')