C# 比较两组数据(x,y)
我已经将数字数据存储在带有坐标(xValues,yValues)的列表中,如果我想将这组数据与另一组数据进行比较(加、减、除…),我必须意识到如果xValues不匹配,我就无法进行比较(因为没有什么可比较的)。所以我需要在另一个集合中实际存在的“缺失”x值之间进行线性插值,并生成新的点。请检查此图片: 红线上的青色方框表示存储的点(xValues2),并且(通常)它们不会与其他设置的xValues(xValues1)匹配。绿线上的两个正方形是所需生成点的示例。有了它们,我可以毫无问题地处理这两张图 对于线性插值,它非常简单:如果我有两个点(x0,y0)和(x1,y1),我想在它们之间添加一个新点,给定一个“x2”: 为了实现这一点,我认为我必须实现如下内容:C# 比较两组数据(x,y),c#,dataset,interpolation,C#,Dataset,Interpolation,我已经将数字数据存储在带有坐标(xValues,yValues)的列表中,如果我想将这组数据与另一组数据进行比较(加、减、除…),我必须意识到如果xValues不匹配,我就无法进行比较(因为没有什么可比较的)。所以我需要在另一个集合中实际存在的“缺失”x值之间进行线性插值,并生成新的点。请检查此图片: 红线上的青色方框表示存储的点(xValues2),并且(通常)它们不会与其他设置的xValues(xValues1)匹配。绿线上的两个正方形是所需生成点的示例。有了它们,我可以毫无问题地处理这两
编辑:对不起,如果我没有正确地解释我 这里我有一个例子(用Excel完成): 请注意,我不能直接将Series1和Series2(+)或任何其他操作相加,因为它们中的X间距不同。所以我想在需要时在序列1中生成一个新点 为此,我想简单地使用线性插值。假设系列1中有P1(0,40)和P2(0,60),但系列2中有一个点(1,10)。我需要用(1,50)坐标在P1和P2之间生成点P3 我试着用SkipWhile做这件事,比较两个系列的下一个X值,如果系列1的X值更低,那么在newSeries中添加该X值和相应的Y值。否则,使用XValue2生成Y并将其添加到newSeries。以下是我的一次尝试(无效):
List series1X=新列表{0,2,4,6,8};
列表序列1y=新列表{120、100、110、105、70};
列表序列2x=新列表{0,1,7,8,9};
List newSeries1X=新列表();
List newSeries1Y=新列表();
double lastX1=series1X[series1X.Count()-1];
int i=0;
(next1X p首先,我可能会使用一个适当的“点”类,该类包含x和y坐标,而不是每个坐标的两个单独列表。然后,您可以使用该方法快速遍历它们:
IEnumerable<PointF> points0 = ...
IEnumerable<PointF> points0 = ...
float x2 = ...
IEnumerable<PointF> newPoints = point0.Zip(points1,
(p0, p1) => new PointF(p0.X, p0.Y + (x2-p0.X) * (p1.Y-p0.Y) / (p1.X-p0.X)));
此解决方案通过从第一对/最后一对点向外线性“投影”数据来处理第一个series2X[0]
和series2X[n]>series1X[m]
的情况
下面是另一个使用枚举数的解决方案(主要是),但它并不像我希望的那样优雅。它可能会有一些改进:
bool hasS1 = true, hasS2 = true, preinterp = true;
double x0 = 0, y0 = 0, x1 = 0, y1 = 0, x = 0, y = 0;
using(var s1xEnumerator = series1X.GetEnumerator())
using(var s1yEnumerator = series1Y.GetEnumerator())
using(var s2xEnumerator = series2X.GetEnumerator())
{
hasS1 = s1xEnumerator.MoveNext();
hasS2 = s2xEnumerator.MoveNext();
s1yEnumerator.MoveNext();
while(hasS1 && hasS2)
{
x1 = s1xEnumerator.Current;
y1 = s1yEnumerator.Current;
x = s2xEnumerator.Current;
if (x1 <= x)
{
newSeries1X.Add(x1);
newSeries1Y.Add(y1);
hasS1 = s1xEnumerator.MoveNext();
s1yEnumerator.MoveNext();
preinterp = false;
if (hasS1)
{
x0 = x1;
y0 = y1;
}
if (x1 == x)
{
hasS2 = s2xEnumerator.MoveNext();
}
}
else
{
// we have to look ahead to get the next interval to interpolate before x0
if (preinterp)
{
x0 = x1;
y0 = y1;
x1 = series1X[1]; // can't peek with enumerator
y1 = series1Y[1];
preinterp = false;
}
y = y0 + (y1 - y0) * (x - x0) / (x1 - x0);
newSeries1X.Add(x);
newSeries1Y.Add(y);
hasS2 = s2xEnumerator.MoveNext();
}
}
while(hasS1)
{
newSeries1X.Add(s1xEnumerator.Current);
newSeries1Y.Add(s1yEnumerator.Current);
hasS1 = s1xEnumerator.MoveNext();
s1yEnumerator.MoveNext();
}
while(hasS2)
{
x = s2xEnumerator.Current;
y = y0 + (y1 - y0) * (x - x0) / (x1 - x0);
newSeries1X.Add(x);
newSeries1Y.Add(y);
hasS2 = s2xEnumerator.MoveNext();
}
}
bool hasS1=true,hasS2=true,preinterp=true;
双x0=0,y0=0,x1=0,y1=0,x=0,y=0;
使用(var s1xEnumerator=series1X.GetEnumerator())
使用(var s1yEnumerator=series1Y.GetEnumerator())
使用(var s2xEnumerator=series2X.GetEnumerator())
{
hasS1=s1xEnumerator.MoveNext();
hasS2=s2xEnumerator.MoveNext();
s1yEnumerator.MoveNext();
而(hasS1和hasS2)
{
x1=S1Xe分子电流;
y1=S1Y分子电流;
x=S2Xe分子电流;
如果(x1用于处理具有不同间距的两个系列,我首先需要在第一组中生成点,然后在第二组中生成点(使用相同的方法),最后对点进行求和
以下是该方法的代码:
using OxyPlot.Series;
using OxyPlot;
namespace Algorithm1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<DataPoint> S1 = new List<DataPoint> ();
List<DataPoint> S2 = new List<DataPoint>();
List<DataPoint> NS1 = new List<DataPoint>();
S1.Add(new DataPoint(4, 10));
S1.Add(new DataPoint(6, 20));
S1.Add(new DataPoint(8, 15));
S1.Add(new DataPoint(9, 70));
S1.Add(new DataPoint(10, 5));
S2.Add(new DataPoint(1, 0));
S2.Add(new DataPoint(2, 0));
S2.Add(new DataPoint(3, 0));
S2.Add(new DataPoint(6, 0));
S2.Add(new DataPoint(7, 0));
S2.Add(new DataPoint(8.1, 0));
S2.Add(new DataPoint(8.2, 0));
S2.Add(new DataPoint(8.3, 0));
S2.Add(new DataPoint(8.4, 0));
S2.Add(new DataPoint(9, 0));
S2.Add(new DataPoint(9.75, 0));
S2.Add(new DataPoint(11, 0));
S2.Add(new DataPoint(12, 0));
S2.Add(new DataPoint(16, 0));
NS1 = GetMiddlePoints(S1, S2);
foreach (DataPoint pointin NS1)
{
MessageBox.Show( point.X.ToString()+" : "+ point.Y.ToString());
}
}
#region GetMiddlePoints
private List<DataPoint> GetMiddlePoints(List<DataPoint> S1, List<DataPoint> S2)
{
List<DataPoint> NS1 = new List<DataPoint>();
int i = 0;
int j = S2.TakeWhile(p => p.X < S1[0].X).Count();
int PointsInS1 = S1.Count;
int PointsInS2 = S2.Count;
DataPoint newPoint = new DataPoint();
while (i < PointsInS1 )
{
if (j < PointsInS2 )
{
if (S1[i].X < S2[j].X)
{
newPoint = S1[i];
NS1.Add(newPoint );
i++;
}
else if (S1[i].X == S2[j].X)
{
newPoint = S1[i];
NS1.Add(newPoint );
i++;
j++;
}
else if (S1[i].X > S2[j].X)
{
newPoint .X = S2[j].X;
newPoint .Y = S1[i-1].Y + (S2[j].X - S1[i-1].X) * (S1[i].Y - S1[i-1].Y) / (S1[i].X - S1[i-1].X);
NS1.Add(newPoint );
j++;
}
}
if (j == PointsInS2 )
{
newPoint = S1[i];
NS1.Add(newPoint );
i++;
}
}
return NS1;
}
#endregion
}
}
使用OxyPlot.Series;
使用氧图;
名称空间算法1
{
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
列表S1=新列表();
列表S2=新列表();
列表NS1=新列表();
S1.添加(新数据点(4,10));
S1.添加(新数据点(6,20));
S1.增加(新数据点(8,15));
S1.增加(新数据点(9,70));
S1.添加(新数据点(10,5));
S2.添加(新数据点(1,0));
S2.添加(新数据点(2,0));
S2.添加(新数据点(3,0));
S2.添加(新数据点(6,0));
S2.添加(新数据点(7,0));
S2.增加(新数据点(8.1,0));
S2.增加(新数据点(8.2,0));
S2.增加(新数据点(8.3,0));
S2.增加(新数据点(8.4,0));
S2.添加(新数据点(9,0));
S2.增加(新数据点(9.75,0));
S2.添加(新数据点(11,0));
S2.添加(新数据点(12,0));
S2.添加(新数据点(16,0));
NS1=获取中间点(S1,S2);
foreach(NS1中的数据点)
{
Show(point.X.ToString()+”:“+point.Y.ToString());
}
}
#区域中间点
私有列表GetMiddlePoints(列表S1、列表S2)
{
列表NS1=新列表();
int i=0;
intj=S2.TakeWhile(p=>p.XIEnumerable<double> y2values =
xValues1.Zip(yValues1, (x, y) => new { x, y }).Zip(
xValues2.Zip(yValues2, (x, y) => new { x, y }),
(p0, p1) => p0.y + (x2-p0.x) * (p1.y-p0.y) / (p1.x-p0.x));
List<double> series1X = new List<double> { 0, 2, 4, 6, 8 };
List<double> series1Y = new List<double> { 120, 100, 110, 105, 70 };
List<double> series2X = new List<double> { 0, 1, 7, 8, 9 };
// in the worst case there are n + m new points
List<double> newSeries1X = new List<double>(series1X.Count + series2X.Count);
List<double> newSeries1Y = new List<double>(series1X.Count + series2X.Count);
int i = 0, j = 0;
for ( ; i < series1X.Count && j < series2X.Count; )
{
if (series1X[i] <= series2X[j])
{
newSeries1X.Add(series1X[i]);
newSeries1Y.Add(series1Y[i]);
if (series1X[i] == series2X[j])
{
j++;
}
i++;
}
else
{
int k = (i == 0) ? i : i - 1;
// interpolate
double y0 = series1Y[k];
double y1 = series1Y[k + 1];
double x0 = series1X[k];
double x1 = series1X[k + 1];
double y = y0 + (y1 - y0) * (series2X[j] - x0) / (x1 - x0);
newSeries1X.Add(series2X[j]);
newSeries1Y.Add(y);
j++;
}
}
for ( ; i < series1X.Count; i++)
{
newSeries1X.Add(series1X[i]);
newSeries1Y.Add(series1Y[i]);
}
for ( ; j < series2X.Count; j++)
{
// interpolate
double y0 = series1Y[i - 2];
double y1 = series1Y[i - 1];
double x0 = series1X[i - 2];
double x1 = series1X[i - 1];
double y = y0 + (y1 - y0) * (series2X[j] - x0) / (x1 - x0);
newSeries1X.Add(series2X[j]);
newSeries1Y.Add(y);
}
newSeries1X = { 0, 1, 2, 4, 6, 7, 8, 0 }
newSeries1Y = { 120, 110, 100, 110, 105, 87.5, 70, 52.5 }
bool hasS1 = true, hasS2 = true, preinterp = true;
double x0 = 0, y0 = 0, x1 = 0, y1 = 0, x = 0, y = 0;
using(var s1xEnumerator = series1X.GetEnumerator())
using(var s1yEnumerator = series1Y.GetEnumerator())
using(var s2xEnumerator = series2X.GetEnumerator())
{
hasS1 = s1xEnumerator.MoveNext();
hasS2 = s2xEnumerator.MoveNext();
s1yEnumerator.MoveNext();
while(hasS1 && hasS2)
{
x1 = s1xEnumerator.Current;
y1 = s1yEnumerator.Current;
x = s2xEnumerator.Current;
if (x1 <= x)
{
newSeries1X.Add(x1);
newSeries1Y.Add(y1);
hasS1 = s1xEnumerator.MoveNext();
s1yEnumerator.MoveNext();
preinterp = false;
if (hasS1)
{
x0 = x1;
y0 = y1;
}
if (x1 == x)
{
hasS2 = s2xEnumerator.MoveNext();
}
}
else
{
// we have to look ahead to get the next interval to interpolate before x0
if (preinterp)
{
x0 = x1;
y0 = y1;
x1 = series1X[1]; // can't peek with enumerator
y1 = series1Y[1];
preinterp = false;
}
y = y0 + (y1 - y0) * (x - x0) / (x1 - x0);
newSeries1X.Add(x);
newSeries1Y.Add(y);
hasS2 = s2xEnumerator.MoveNext();
}
}
while(hasS1)
{
newSeries1X.Add(s1xEnumerator.Current);
newSeries1Y.Add(s1yEnumerator.Current);
hasS1 = s1xEnumerator.MoveNext();
s1yEnumerator.MoveNext();
}
while(hasS2)
{
x = s2xEnumerator.Current;
y = y0 + (y1 - y0) * (x - x0) / (x1 - x0);
newSeries1X.Add(x);
newSeries1Y.Add(y);
hasS2 = s2xEnumerator.MoveNext();
}
}
using OxyPlot.Series;
using OxyPlot;
namespace Algorithm1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<DataPoint> S1 = new List<DataPoint> ();
List<DataPoint> S2 = new List<DataPoint>();
List<DataPoint> NS1 = new List<DataPoint>();
S1.Add(new DataPoint(4, 10));
S1.Add(new DataPoint(6, 20));
S1.Add(new DataPoint(8, 15));
S1.Add(new DataPoint(9, 70));
S1.Add(new DataPoint(10, 5));
S2.Add(new DataPoint(1, 0));
S2.Add(new DataPoint(2, 0));
S2.Add(new DataPoint(3, 0));
S2.Add(new DataPoint(6, 0));
S2.Add(new DataPoint(7, 0));
S2.Add(new DataPoint(8.1, 0));
S2.Add(new DataPoint(8.2, 0));
S2.Add(new DataPoint(8.3, 0));
S2.Add(new DataPoint(8.4, 0));
S2.Add(new DataPoint(9, 0));
S2.Add(new DataPoint(9.75, 0));
S2.Add(new DataPoint(11, 0));
S2.Add(new DataPoint(12, 0));
S2.Add(new DataPoint(16, 0));
NS1 = GetMiddlePoints(S1, S2);
foreach (DataPoint pointin NS1)
{
MessageBox.Show( point.X.ToString()+" : "+ point.Y.ToString());
}
}
#region GetMiddlePoints
private List<DataPoint> GetMiddlePoints(List<DataPoint> S1, List<DataPoint> S2)
{
List<DataPoint> NS1 = new List<DataPoint>();
int i = 0;
int j = S2.TakeWhile(p => p.X < S1[0].X).Count();
int PointsInS1 = S1.Count;
int PointsInS2 = S2.Count;
DataPoint newPoint = new DataPoint();
while (i < PointsInS1 )
{
if (j < PointsInS2 )
{
if (S1[i].X < S2[j].X)
{
newPoint = S1[i];
NS1.Add(newPoint );
i++;
}
else if (S1[i].X == S2[j].X)
{
newPoint = S1[i];
NS1.Add(newPoint );
i++;
j++;
}
else if (S1[i].X > S2[j].X)
{
newPoint .X = S2[j].X;
newPoint .Y = S1[i-1].Y + (S2[j].X - S1[i-1].X) * (S1[i].Y - S1[i-1].Y) / (S1[i].X - S1[i-1].X);
NS1.Add(newPoint );
j++;
}
}
if (j == PointsInS2 )
{
newPoint = S1[i];
NS1.Add(newPoint );
i++;
}
}
return NS1;
}
#endregion
}
}