C# 数据集中近似相等点的合并
我正在寻找一种算法,它可以快速运行一段短时间(我不确定这是否正是您想要的,但还没有发布任何其他答案,所以我们开始吧 我从一个图形的角度来看它。如果我在看一个图形,我想确定哪些点在水平方向上是相似的,这些点最终会相对于图形的比例。所以我做了一个函数,它接受比例的一个百分比,你想被认为是相同的。然后它取这个百分比,乘以It乘以数据集之间的最大差值 此外,相似值始终与当前定位平台的平均值进行比较。一旦检测到平台结束,它将x加在一起,除以2得到中间值,然后取平均y值并将其作为最终数据点进行添加 在没有获得好的样本数据的情况下,我所要做的就是我制作的非常糟糕的数据生成器。但在我的测试中,1%以内的值通常会消除大约一半的数据点 现在需要注意的是,这是一维的,x距离完全被忽略了。你可以很容易地将它扩展到二维。我考虑做的另一件事是不输出单个数据点来表示高原,而是输出平均值的起点和终点C# 数据集中近似相等点的合并,c#,algorithm,C#,Algorithm,我正在寻找一种算法,它可以快速运行一段短时间(我不确定这是否正是您想要的,但还没有发布任何其他答案,所以我们开始吧 我从一个图形的角度来看它。如果我在看一个图形,我想确定哪些点在水平方向上是相似的,这些点最终会相对于图形的比例。所以我做了一个函数,它接受比例的一个百分比,你想被认为是相同的。然后它取这个百分比,乘以It乘以数据集之间的最大差值 此外,相似值始终与当前定位平台的平均值进行比较。一旦检测到平台结束,它将x加在一起,除以2得到中间值,然后取平均y值并将其作为最终数据点进行添加 在没有获
namespace PointCondenser
{
public static class Extensions
{
static public bool AlmostEqual<T>(this T value, T value2, T epsilon)
{
return (Math.Abs((dynamic)value - value2) < epsilon);
}
}
public struct Point
{
public Point(double x, double y)
{
X = x;
Y = y;
}
public override string ToString()
{
return string.Format("{0}\t{1}", X, Y);
}
public double X;
public double Y;
}
class Program
{
static public Point RandomYPoint(int i)
{
var r = new Random();
var r2 = new Random(i);
var variance = r2.NextDouble() / 100;
return new Point(i, Math.Abs(r.NextDouble() - variance) * 100);
}
static public IEnumerable<Point> SmoothPoints(IEnumerable<Point> points, double percent)
{
if (percent <= 0 || percent >= 1)
throw new ArgumentOutOfRangeException("percent", "Percentage outside of logical bounds");
var final = new List<Point>();
var apoints = points.ToArray();
var largestDifference = apoints.Max(x => x.Y) - apoints.Min(x => x.Y);
var epsilon = largestDifference * percent;
var currentPlateau = new List<Point> { apoints[0] };
for (var i = 1; i < apoints.Length; ++i)
{
var point = apoints[i];
if (point.Y.AlmostEqual(currentPlateau.Average(x => x.Y), epsilon))
currentPlateau.Add(point);
else
{
var x = (currentPlateau[0].X + currentPlateau[currentPlateau.Count - 1].X) / 2.0;
var y = currentPlateau.Average(z => z.Y);
currentPlateau.Clear();
currentPlateau.Add(point);
final.Add(new Point(x, y));
}
}
return final;
}
static void Main(string[] args)
{
var r = new Random();
var points = new List<Point>();
for (var i = 0; i < 100; ++i)
{
for (var n = 0; n < r.Next(1, 5); ++n)
{
var p = RandomYPoint(points.Count);
points.Add(p);
Console.WriteLine(p);
}
Thread.Sleep(r.Next(10, 250));
}
Console.Write("\n\n Condensed \n\n");
var newPoints = SmoothPoints(points, .01);
foreach (var p in newPoints)
Console.WriteLine(p);
}
}
}
名称空间点冷凝器
{
公共静态类扩展
{
静态公共bool AlmostEqual(此T值,T值2,Tε)
{
返回值(数学Abs((动态)值-value2)x.Y)-apoints.Min(x=>x.Y);
varε=最大差值*百分比;
var currentplation=新列表{apoints[0]};
对于(变量i=1;ix.Y),ε))
当前平台。添加(点);
其他的
{
变量x=(CurrentPlatform[0].x+CurrentPlatform[CurrentPlatform.Count-1].x)/2.0;
var y=当前平台平均值(z=>z.y);
current.Clear();
当前平台。添加(点);
最终添加(新点(x,y));
}
}
返回最终结果;
}
静态void Main(字符串[]参数)
{
var r=新的随机变量();
var points=新列表();
对于(变量i=0;i<100;++i)
{
对于(var n=0;n
无参数聚类的另一种方法是合并最近的数据点。
也就是说,在每个过程中,您将找到两个数据点之间的最小间隙,然后将这些对与该间隙合并
因此,每个过程的粒度都会降低。但是,除非根据比较的属性对数据点进行排序,否则查找最小间隙可能会非常昂贵。回顾过去,我也可以使用线性回归进行此操作:如果斜率接近于零,并且到下一个点的斜率与平均斜率o相似如果在高原上的前面的点,然后登记下一个点来合并和继续。你介意详细说明你认为是什么吗?它是否在一定的百分比之内,到一个小数点?如果我知道,我可以自己写算法:P.“近似”在这里对应于人类的概念。“我能看出这两点其实是一样的,”我意识到这很难翻译成代码。到目前为止,我的想法大致是,给定点(x1,y1),(x2,y2)和(x3,y3),”y2-y1+1。这是一个有趣的问题。因为你的用户名中有一些与Zelda相关的东西。一些lke,或者其他与之相关的东西?警告:这是一个很大的领域…也许阈值k-均值算法会有所帮助:低于3个元素它什么都不做,高于它寻找点云,那么这些云将become一个单点。嗯…我更喜欢没有参数的方法,但我会尝试一下。会让你知道它是如何工作的:PIt工作,但由于我的数据集变化很大,需要一段时间才能确定一组好的参数。仍然在寻找一个无参数的方法,但我现在就使用它。谢谢!你可以发布一个数据集exa吗我想知道你们的电视机是什么样子的?好了。(简言之,我知道——我还没跑呢。)
97 54686024814922.8
118 406406320535.935
148 24095826539423.7
159 1625625061816.08
182 1625625089631.21
194 21068100428092.9
247 54686024895222.1
2 196412376940671
123 206108518197124
135 194488685387149
148 178463949513298
154 192912098976702
156 195042451997727
161 195221254214493
168 204760073508681
172 189240741651297
182 191554457423846
187 215014126955355
201 202294866774063
2 196412376940671
123 206108518197124
135 194488685387149
148 178463949513298
157 194391935062974
168 204760073508681
172 189240741651297
182 191554457423846
187 215014126955355
201 202294866774063
2 299777367852602
26 263467434856928
35 293412234811901
83 242768805551742
104 226333969841383
107 227548774800053
178 229173574175201
181 229224441416751
204 244334414017228
206 245258151638118
239 198782930497571
2 299777367852602
26 263467434856928 (May be merged
35 293412234811901 depending on parameters)
83 242768805551742
105.5 226941372320718
179.5 229199007795976
205 244796282827673
239 198782930497571
namespace PointCondenser
{
public static class Extensions
{
static public bool AlmostEqual<T>(this T value, T value2, T epsilon)
{
return (Math.Abs((dynamic)value - value2) < epsilon);
}
}
public struct Point
{
public Point(double x, double y)
{
X = x;
Y = y;
}
public override string ToString()
{
return string.Format("{0}\t{1}", X, Y);
}
public double X;
public double Y;
}
class Program
{
static public Point RandomYPoint(int i)
{
var r = new Random();
var r2 = new Random(i);
var variance = r2.NextDouble() / 100;
return new Point(i, Math.Abs(r.NextDouble() - variance) * 100);
}
static public IEnumerable<Point> SmoothPoints(IEnumerable<Point> points, double percent)
{
if (percent <= 0 || percent >= 1)
throw new ArgumentOutOfRangeException("percent", "Percentage outside of logical bounds");
var final = new List<Point>();
var apoints = points.ToArray();
var largestDifference = apoints.Max(x => x.Y) - apoints.Min(x => x.Y);
var epsilon = largestDifference * percent;
var currentPlateau = new List<Point> { apoints[0] };
for (var i = 1; i < apoints.Length; ++i)
{
var point = apoints[i];
if (point.Y.AlmostEqual(currentPlateau.Average(x => x.Y), epsilon))
currentPlateau.Add(point);
else
{
var x = (currentPlateau[0].X + currentPlateau[currentPlateau.Count - 1].X) / 2.0;
var y = currentPlateau.Average(z => z.Y);
currentPlateau.Clear();
currentPlateau.Add(point);
final.Add(new Point(x, y));
}
}
return final;
}
static void Main(string[] args)
{
var r = new Random();
var points = new List<Point>();
for (var i = 0; i < 100; ++i)
{
for (var n = 0; n < r.Next(1, 5); ++n)
{
var p = RandomYPoint(points.Count);
points.Add(p);
Console.WriteLine(p);
}
Thread.Sleep(r.Next(10, 250));
}
Console.Write("\n\n Condensed \n\n");
var newPoints = SmoothPoints(points, .01);
foreach (var p in newPoints)
Console.WriteLine(p);
}
}
}