Matlab 如何使用给定数据绘制三维数密度散点图?

Matlab 如何使用给定数据绘制三维数密度散点图?,matlab,plot,matlab-figure,Matlab,Plot,Matlab Figure,我有一个立方体盒子,每个方向都有300个。我有一些数据(包含X,Y,Z坐标),它们代表了这个框中近100万个数据点的分布。我想为它们的数字密度指定一种颜色(这是一个密集的数量,用于描述可数对象在本例中的数据点的集中程度)。换句话说,使用颜色来说明哪个部分在数据点方面比其他部分更精简。最终图像中颜色栏的索引应表示使用该颜色指定的数据点的百分比 我试着将立方体盒子中的整个空间分割成100万个小立方体(每个立方体在所有方向上都有3个长度)。通过计算这些立方体中粒子的数量,我将知道它们在盒子中的分布情况

我有一个立方体盒子,每个方向都有300个。我有一些数据(包含X,Y,Z坐标),它们代表了这个框中近100万个数据点的分布。我想为它们的数字密度指定一种颜色(这是一个密集的数量,用于描述可数对象在本例中的数据点的集中程度)。换句话说,使用颜色来说明哪个部分在数据点方面比其他部分更精简。最终图像中颜色栏的索引应表示使用该颜色指定的数据点的百分比

我试着将立方体盒子中的整个空间分割成100万个小立方体(每个立方体在所有方向上都有3个长度)。通过计算这些立方体中粒子的数量,我将知道它们在盒子中的分布情况以及其中存在的数据点的数量。然后我可以为它们指定一种我在计数和指定时没有成功的颜色。如有任何建议,我们将不胜感激

%reading the files
[FileName,PathName,FilterIndex] = uigetfile('H:\*.txt','MultiSelect','on');
numfiles = size(FileName,2);%('C:\final1.txt');
j=1;
X=linspace(0,300,100);
for ii = 1:numfiles
    FileName{ii}
    entirefile = fullfile(PathName,FileName{ii});
    a = importdata(entirefile);
    x = a(:,2);
    y = a(:,3);
    z = a(:,4);
    %% I DON'T KNOW HOW TO CREAT THIS LOOP TO COUNT FOR THE NUMBER OF PARTICLES WITHIN EACH DEFINED CUBE %%
    for jj = 2:size(X,2) 
        %for kk=1:m
        if x(:)<X(jj) & y(:)<X(jj) & z(:)<X(jj)
           x;
        end
        %end
    end
    h=figure(j);
    scatter3(x, y, z, 'filled', 'MarkerSize', 20);
    cb = colorbar();
    cb.Label.String = 'Probability density estimate';
end
%正在读取文件
[FileName,PathName,FilterIndex]=uigetfile('H:\*.txt','MultiSelect','on');
numfiles=大小(文件名,2);%('C:\final1.txt');
j=1;
X=linspace(0300100);
对于ii=1:numfiles
文件名{ii}
entirefile=fullfile(路径名,文件名{ii});
a=导入数据(完整);
x=a(:,2);
y=a(:,3);
z=a(:,4);
%%我不知道如何创建此循环来计算每个已定义立方体%%内的粒子数
对于jj=2:尺寸(X,2)
%对于kk=1:m

如果x(:)这里有一种计算点云三维密度的方法。尽管我对您提供的示例数据感到震惊,但与您的示例图像相比,它并没有产生相同的3D分布

为了计算密度,该方法分为几个步骤:

  • 计算
    [X,Y]
    平面中的二维密度:计算每个
    (X,Y)
    箱子中放置的点数。然而,在这个阶段,这个点数包含了给定箱子的所有
    Z
  • 对于每个非空的
    (x,y)
    bin,计算沿
    Z
    列的分布。现在,我们有了每个
    (x,y,z)
    箱子中落下的点数。计算密度/百分比只需将每个计数除以总点数即可
  • 现在,对于每个非空的
    (x,y,z)
    箱,我们确定属于该箱的点的线性指数。然后,我们将bin值(颜色、百分比或与此bin关联的任何值)分配给所有已识别的点
  • 显示结果
在代码中,它是这样的:

%% Import sample data
entirefile = '1565015520323.txt' ;
a = importdata(entirefile);
x = a(:,1);
y = a(:,2);
z = a(:,3);
npt = numel(x) ; % Total Number of Points

%% Define domain and grid parameters
nbins    = 100 ;
maxDim   = 300 ;
binEdges = linspace(0,maxDim,nbins+1) ;

%% Count density
% we start counting density along in the [X,Y] plane (Z axis aglomerated)
[Nz,binEdges,~,binX,binY] = histcounts2(y,x,binEdges,binEdges) ;

% preallocate 3D containers
N3d = zeros(nbins,nbins,nbins) ; % 3D matrix containing the counts
Npc = zeros(nbins,nbins,nbins) ; % 3D matrix containing the percentages
colorpc = zeros(npt,1) ;         % 1D vector containing the percentages

% we do not want to loop on every block of the domain because:
%   - depending on the grid size there can be many
%   - a large number of them can be empty
% So we first find the [X,Y] blocks which are not empty, we'll only loop on
% these blocks.
validbins = find(Nz) ;                              % find the indices of non-empty blocks
[xbins,ybins] = ind2sub([nbins,nbins],validbins) ;  % convert linear indices to 2d indices
nv = numel(xbins) ;                                 % number of block to process

% Now for each [X,Y] block, we get the distribution over a [Z] column and
% assign the results to the full 3D matrices
for k=1:nv
    % this block coordinates
    xbin = xbins(k) ;
    ybin = ybins(k) ;

    % find linear indices of the `x` and `y` values which are located into this block
    idx = find( binX==xbin & binY==ybin ) ;
    % make a subset with the corresponding 'z' value
    subZ = z(idx) ;
    % find the distribution and assign to 3D matrices
    [Nz,~,zbins] = histcounts( subZ , binEdges ) ;
    N3d(xbin,ybin,:) = Nz ;         % total counts for this block
    Npc(xbin,ybin,:) = Nz ./ npt ;  % density % for this block

    % Now we have to assign this value (color or percentage) to all the points
    % which were found in the blocks
    vzbins = find(Nz) ;
    for kz=1:numel(vzbins)
        thisColorpc = Nz(vzbins(kz)) ./ npt * 100 ;
        idz   = find( zbins==vzbins(kz) ) ;
        idx3d = idx(idz) ;
        colorpc(idx3d) = thisColorpc ;
    end

end
assert( sum(sum(sum(N3d))) == npt ) % double check we counted everything

%% Display final result
h=figure;
hs=scatter3(x, y, z, 3 , colorpc ,'filled' );
xlabel('X'),ylabel('Y'),zlabel('Z')
cb = colorbar ;
cb.Label.String = 'Probability density estimate';
正如我在开始时所说,结果与示例图像略有不同。此样本集产生以下分布:

如果需要一种“双重检查”结果是否为垃圾的方法,可以查看每个轴上的二维密度结果,并检查其是否与点的外观分布相匹配:

%% Verify on 3 axis:
Nz = histcounts2(y,x,binEdges,binEdges) ./ npt *100 ;
Nx = histcounts2(z,y,binEdges,binEdges) ./ npt *100 ;
Ny = histcounts2(x,z,binEdges,binEdges) ./ npt *100 ;
figure
ax1=subplot(1,3,1) ; bz = plotDensity(Nz,ax1) ; xlabel('X'),ylabel('Y') ;
ax2=subplot(1,3,2) ; bx = plotDensity(Nx,ax2) ; xlabel('Y'),ylabel('Z') ;
ax3=subplot(1,3,3) ; by = plotDensity(Ny,ax3) ; xlabel('Z'),ylabel('X') ;
单击图像以查看更大的图像:

plotDensity.m的代码

function hp = plotDensity(Ndist,hax)
    if nargin<2 ; hax = axes ; end
    hp = bar3(Ndist,'Parent',hax) ;
    for k = 1:length(hp)
        zdata = hp(k).ZData;
        hp(k).CData = zdata;
        hp(k).FaceColor = 'interp';
    end
    shading interp
函数hp=plotDensity(Ndist,hax)

如果narginI建议您创建一个每个人都可以复制的小型可行样本数据集。人们无法处理他们无权访问的数据集@谢谢你。我已添加到采样数据的链接。@Mehdi。如果您想要点的数量而不是它们的密度%,那么只需替换以下行:
thiscorrorpc=Nz(vzbins(kz))./npt*100通过更简单的
thiscorrorpc=Nz(vzbins(kz))。(并明显更改颜色栏的标题)感谢您的明确解释。非常感谢