如何在 python 中对 3D 数据进行聚类和可视化

数据挖掘 Python 聚类 可视化
2022-03-05 04:39:27

我有一个 x,y,z 点的 3D 数据集,有 2 个类别,A 类和 B 类。我的最终目标是将 B 类中的所有点聚集成体积(球体/云),并找到靠近边缘的 A 类的所有点那些卷。我假设球体内部不会有任何 A 类点。B 类的点在空间上高度聚集,因此集群可能非常明显。

在 2D GIS 中,我使用核密度估计和 K-Means 聚类来完成类似的任务,但是因为我正在处理 3D 数据,而且是非地理数据(相对于虚构的 0,0,0 原点),并且因为我是熟悉 python 数据科学工具,我认为 matplotlib/scipy/numpy/sklearn/pandas/etc 可能是更好的工具。但我不确定哪些工具和库特别适合看。

所以我的问题是2倍的:

  1. 哪些库非常适合查找 3D 集群以及 A 类“接近”它们的点
  2. 什么工具可以让我可视化集群,最好是在允许我缩放/平移/旋转的交互式图中
3个回答

以下步骤是实现您的结果的一种方法。我使用了Wolfram 语言,但该方法可以通过任何具有正确库的语言应用。

  1. FindClusters 对于 A 类数据 ( dataA),
  2. 计算 ConvexHullMesh 每个集群的
  3. 对于 B 类 ( dataB) 中的每个点,计算 RegionDistance 每个 A 类船体的
  4. 以及 最近的 A 类船体PickdataB点。

我们可以从对象属性中收集相关的 3D 示例数据。"AdministrativeDivision" Entity

dataA =
  Select[FreeQ[_Missing]]@
   EntityValue[
    EntityClass["AdministrativeDivision", {"ParentRegion" -> Entity["Country", "UnitedStates"]}]
    , {"GiniIndex", "TotalVotingRate", "HomeOwnershipRate"}];
First@dataA
{0.4776, 56.3712%, 70.7%}

我使用FindClusters"MeanShift"集群的方法。发现了两个集群。

clusters = FindClusters[dataA, Method -> "MeanShift"];
Length@clusters
2

每个集群的列表通过ConvexHullMesh以下方式获得

hulls = ConvexHullMesh /@ clusters

在此处输入图像描述

通过将 a ListPointPlot3Dofclusters与 a Graphics3Dof hulls(with lowOpacity使它们透明)与结合起来,可以用它们的内部点来可视化它们Show

cp =
 Show[
  ListPointPlot3D[
   clusters
   , PlotStyle -> ColorData[110]
   , PlotTheme -> {"Web", "FrameGrid"}
   , BoxRatios -> Automatic]
  , Graphics3D[
     {Opacity[.1]
     , MapIndexed[
       {ColorData[110] @@ #2, EdgeForm[{Thin, Opacity[.1], ColorData[110] @@ #2}], #1} &
       , hulls]}]
  ]

在此处输入图像描述

对于 B 类示例数据,我们需要集群外壳之外的点。我们可以在ofCuboid周围创建一个通过取. 这个区域可以用 可视化RegionUnionhullshullsRegionDifferenceRegionPlot3D

With[
  {ru = RegionUnion[hulls]}
  , rd =
   RegionDifference[
    Cuboid @@ Transpose[
      MapAt[Ceiling[#, 0.01] &, {All, 2}]@
       MapAt[Floor[#, 0.01] &, {All, 1}]@
        RegionBounds@ru]
    , ru]
  ];
RegionPlot3D[rd
 , PlotStyle -> Opacity[.1]
 , Axes -> True]

在此处输入图像描述

然后我们可以RandomPoint在这个区域内为 生成 s dataB

SeedRandom[19283745]
dataB = RandomPoint[DiscretizeRegion@rd, 20];

这些dataB点可以与dataA聚类图结合使用Show所有dataB点都在dataA船体之外。

Show[
 cp
 , ListPointPlot3D[dataB
  , PlotStyle -> Black]
 ]

在此处输入图像描述

现在我们有了示例 B 类数据 ( dataB),我们可以计算RegionDistance每个点到每个 A 类的数据hulls然后通过Ordering这些距离,First入口给出了点最接近的船体。

nc =
 First /@
  Ordering /@
   Transpose@
    Through[
     Function[r, RegionDistance[r, #] &, Listable][hulls][dataB]
     ]
{2, 1, 2, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1}

最后,我们通过它们最近的船体来Pick确定dataB点,并将它们的图与dataA集群图结合起来ShowdataB点已被着色以指示它们最近的dataA集群。

pncB = Pick[dataB, nc, #] & /@ Range@Length@hulls;

Show[
 cp
 , ListPointPlot3D[
  pncB
  , PlotStyle -> ColorData[104]
  , BoxRatios -> Automatic
  ]
 ]

在此处输入图像描述

希望这可以帮助。

edmund的回答非常酷,因为它显示了我需要的算法和方法,但不幸的是,他的回答是关于我不知道的 wolfram 语言,我现在真的不想学习一门新语言。但是一些挖掘和谷歌搜索已经出现了一些不错的选择。特别是 Open3Dsklearn成为我选择的工具。Sklean 的DBScan 算法是我聚类所需要的,sklearn 也有很多其他的聚类算法。

Open3D 更侧重于事物的几何方面和可视化。它可以创建和可视化点云网格,还包括一些数据处理算法,如 dbscan 和重要的 Convex Hull,它允许我将聚集的点云变成网格。它在数据科学方面不如 sklean 强大,但两者的结合确实非常强大,特别是因为 open3d 可以从 numpy 数组创建点云,因此可以创建 pandas 数据帧。

作为奖励,我还发现了Three.js,如果你想在网络上可视化你的结果,这非常棒。它具有非常好的可视化工具、相机控制、交互性等。由于其 WebGL 实现,它的性能非常好,比我预期的要好得多。不幸的是,文档非常有限。它们似乎主要依赖于示例,这些示例通常包含许多很酷的功能,但很难隔离您需要的特定信息。但是通过一些时间投入和反复试验,您可以将使用 pandas/sklearn/open3d 生成的文件在网络上展示给用户。

如果您的数据本质上是线性的,您可能需要研究 PCA。这是一种简单的方法,可以在将数据转换为更少的维度后对其进行可视化: https ://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html