【问题标题】:Divide one-to-two x-y data into top and bottom sets将一对二的 x-y 数据分成顶部和底部集
【发布时间】:2019-12-20 11:08:57
【问题描述】:

我有一个数据集,其中两个 y 值与每个 x 值相关联。如何将数据分为“上”和“下”值?

下面,我展示了一个包含此类数据集的示例。我展示了所需“顶部”和“底部”分组的图像(红色是顶部,紫色是底部)。到目前为止,我最好的想法是使用迭代方法找到一条分割顶部和底部数据的线。这个解决方案很复杂,效果不太好,所以我没有包含它。

import matplotlib.pyplot as plt
import numpy as np

# construct data using piecewise functions
x1 = np.linspace(0, 0.7, 70)
x2 = np.linspace(0.7, 1, 30)
x3 = np.linspace(0.01, 0.999, 100)
y1 = 4.164 * x1 ** 3
y2 = 1 / x2
y3 = x3 ** 4 - 0.1

# concatenate data
x = np.concatenate([x1, x2, x3])
y = np.concatenate([y1, y2, y3])

# I want to be able divide the data by top and bottom,
#  like shown in the chart. The black is the unlabeled data
#  and the red and purple show the top and bottom
plt.scatter(x, y, marker='^', s=10, c='k')
plt.scatter(x1, y1, marker='x', s=0.8, c='r')
plt.scatter(x2, y2, marker='x', s=0.8, c='r')
plt.scatter(x3, y3, marker='x', s=0.8, c='purple')
plt.show()

【问题讨论】:

  • 你能尝试通过点之间的距离来找到上组和下组吗?例如,您可以在每个点周围放置一个小正方形,然后取一个正方形,与它相交的任何正方形都属于同一组,然后继续包括与该组相交的其他点。仅当有明显的非重叠线时才有效。
  • 您是否尝试过计算这些值的移动平均值?您可以使用间隔大小,但我想它应该相对较小。
  • 在您的具体示例中,很容易找到紫色三角形作为集合的下部外壳。使用 Graham 扫描算法(安德鲁的单调链版本)。

标签: python numpy geometry cluster-analysis computational-geometry


【解决方案1】:

您可以通过重新排序数据来创建分隔线。按 x 对所有内容进行排序,然后应用高斯滤波器。这两个数据集严格高于或低于高斯滤波器的结果:

import matplotlib.pyplot as plt
from scipy.ndimage.filters import gaussian_filter1d
import numpy as np

# construct data using piecewise functions
x1 = np.linspace(0, 0.7, 70)
x2 = np.linspace(0.7, 1, 30)
x3 = np.linspace(0.01, 0.999, 100)
y1 = 4.164 * x1 ** 3
y2 = 1 / x2
y3 = x3 ** 4 - 0.1

# concatenate data
x = np.concatenate([x1, x2, x3])
y = np.concatenate([y1, y2, y3])

# I want to be able divide the data by top and bottom,
#  like shown in the chart. The black is the unlabeled data
#  and the red and purple show the top and bottom


idx = np.argsort(x)
newy = y[idx]
newx = x[idx]
gf = gaussian_filter1d(newy, 5)
plt.scatter(x, y, marker='^', s=10, c='k')
plt.scatter(x1, y1, marker='x', s=0.8, c='r')
plt.scatter(x2, y2, marker='x', s=0.8, c='r')
plt.scatter(x3, y3, marker='x', s=0.8, c='purple')
plt.scatter(newx, gf, c='orange')
plt.show()

【讨论】:

    【解决方案2】:

    我会尝试如下:

    • 如有必要,通过增加 X 对点进行排序;

    • 维护上下两个子集的两个索引;

    • 从左到右移动,对于每个新点将其分配给最近的子集并更新相应的索引。

    进程的初始化似乎有点棘手。从前两点开始(它们很有可能属于同一个子集)。进行直到两个点有明显的分离,以便您确定它们属于不同的子集。然后向左返回。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-13
      相关资源
      最近更新 更多