想要在2026年参加这个比赛的,可以加入小编和其它大佬所建的群242845175一起来备赛,为2026年的比赛打基础,也可以私信小编,为你答疑解惑
一、读写文件
internal class Read
{
public static List<Point> pts = new List<Point>();
public static List<Point> Readfile(string filename)
{
string str;
StreamReader sr = new StreamReader(filename);
sr.ReadLine();
while(!sr.EndOfStream)
{
str=sr.ReadLine();
string[]Buf=str.Split(new char[]{','},StringSplitOptions.RemoveEmptyEntries);
Point pt = new Point(Buf[0], double.Parse(Buf[1]), double.Parse(Buf[2]), double.Parse(Buf[3]));
pts.Add(pt);
}
return pts;
}
public static void Savefile(string report)
{
SaveFileDialog sf= new SaveFileDialog();
sf.Filter = "文本数据|*.txt";
sf.Title = "选择保存路径";
sf.FileName = "result";
if(sf.ShowDialog() == DialogResult.OK)
{
StreamWriter sw=new StreamWriter(sf.FileName);
sw.Write(report);
sw.Flush();
}
}
}
二、数据预处理(分组,数据统计)
public static List<List<Point>> ptcode = new List<List<Point>>();
public static List<Point> ptt = Read.pts.OrderBy(p => p.area).ToList();
//将每个不同区域的点进行分组
public static void Classify()
{
double n = 0;
List<Point> points = new List<Point>();
foreach(Point p in ptt)
{
if (p.area != n)
{
n = p.area;
points=new List<Point>();
ptcode.Add(points);
}
points.Add(p);
}
}
//计算平均中心
public static void Averge(out double avx,out double avy)
{
double sumx = Read.pts.Sum(p => p.x);
double sumy = Read.pts.Sum(p => p.y);
avx = sumx / Read.pts.Count;
avy = sumy / Read.pts.Count;
}
三、标准差椭圆计算
//计算每个点的标准差
public static void Allcha()
{
Averge(out double avx, out double avy);
foreach(Point p in Read.pts)
{
p.a = p.x - avx;
p.b = p.y - avy;
}
}
//计算辅助量
public static void Helpword(out double A,out double B,out double C)
{
A = 0;
B = 0;
C = 0;
double sumab = 0;
double sumA = 0;
double sumB = 0;
foreach(Point p in Read.pts)
{
sumA += p.a * p.a;
sumB += p.b * p.b;
sumab += p.a * p.b;
}
A=sumA-sumB;
B=Math.Sqrt(A*A+4*sumab*sumab);
C=2*sumab;
}
//计算椭圆量
public static void Sdsigema(out double sigema,out double SDEx,out double SDEy)
{
sigema = 0;
SDEx = 0;
SDEy = 0;
Helpword(out double A, out double B, out double C);
sigema = Math.Atan((A + B) / C);
double sumn = 0;
double summ = 0;
foreach(Point p in Read.pts)
{
sumn += (p.a * Math.Cos(sigema) + p.b * Math.Sin(sigema))* (p.a * Math.Cos(sigema) + p.b * Math.Sin(sigema));
summ+= (p.a * Math.Sin(sigema) - p.b * Math.Cos(sigema)) * (p.a * Math.Sin(sigema) - p.b * Math.Cos(sigema));
}
SDEx=Math.Sqrt(2*sumn/Read.pts.Count);
SDEy= Math.Sqrt(2 * summ / Read.pts.Count);
}
四、空间矩阵计算
注意公式(5)中的公式有些问题,其分子应为1而非1000,否则与下面答案无法对应
//计算各区的平均中心
public static void Avcenter(List<Point> pts,out double X,out double Y)
{
double sumx=pts.Sum(p => p.x);
double sumy = pts.Sum(p => p.y);
X=sumx/pts.Count;
Y=sumy/pts.Count;
}
//计算各区之间的空间权重矩阵
public static void Weight(int a,int b,out double weight)
{
Avcenter(ptcode[a-1], out double Xa, out double Ya);
Avcenter(ptcode[b - 1], out double Xb, out double Yb);
if (a == b)
{
weight = 0;
}
else { weight = 1 / Math.Sqrt((Xa - Xb) * (Xa - Xb) + (Ya - Yb) * (Ya - Yb)); }
}
五、莫兰指数计算
//计算各区之间的空间权重矩阵
public static void Weight(int a,int b,out double weight)
{
Avcenter(ptcode[a-1], out double Xa, out double Ya);
Avcenter(ptcode[b - 1], out double Xb, out double Yb);
if (a == b)
{
weight = 0;
}
else { weight = 1 / Math.Sqrt((Xa - Xb) * (Xa - Xb) + (Ya - Yb) * (Ya - Yb)); }
}
//计算全局莫兰指数
public static void Allmoulan(out double avX, out double I, out double S)
{
S = 0;
I = 0;
avX = (double)Read.pts.Count / (double)ptcode.Count;
for (int i = 1; i <= ptcode.Count; i++)
{
for (int j = 1; j <= ptcode.Count; j++)
{
Weight(i, j, out double weight);
S += weight;
}
}
double suma = 0;
for (int i = 0; i < ptcode.Count; i++)
{
suma += (ptcode[i].Count - avX) * (ptcode[i].Count - avX);
}
double sumb = 0;
for (int i = 0; i < ptcode.Count; i++)
{
for(int j=0; j < ptcode.Count; j++)
{
Weight(i+1, j+1, out double weight);
sumb += weight * (ptcode[i].Count-avX)* (ptcode[j].Count - avX);
}
}
I = (7.0 / S) * (sumb / suma);
}
//计算局部莫兰指数
public static void Portmolan(int i,out double Ii,out double Si)
{
Allmoulan(out double avX, out double I, out double S);
double suma = 0;
double sumb = 0;
for(int j = 0; j < 7; j++)
{
if ((j+1) == i)
{
continue;
}
Weight(i, j + 1, out double weight);
suma += weight * (ptcode[j ].Count - avX);
sumb += (ptcode[j].Count - avX) * (ptcode[j ].Count - avX);
}
Si = sumb / 6.0;
Ii = ((ptcode[i - 1].Count - avX) / Si) * suma;
}
//计算局部莫兰指数Z得分
public static void Portpoint(out double miu,out double sigema)
{
double sumi = 0;
for(int i=1; i <= 7; i++)
{
Portmolan(i, out double Ii, out double Si);
sumi += Ii;
}
miu = sumi / 7;
double sums = 0;
for (int i = 1; i <= 7; i++)
{
Portmolan(i, out double Ii, out double Si);
sums += (Ii - miu) * (Ii - miu);
}
sigema=Math.Sqrt(sums/6.0);
}
//计算莫兰指数得分
public static void Molan(int i,out double Zi)
{
Portmolan( i, out double Ii, out double Si);
Portpoint(out double miu, out double sigema);
Zi = (Ii - miu) / sigema;
}
六、点的属性
public class Point
{
public string name;
public double x;
public double y;
public double area;
public double a;
public double b;
public Point(string name, double x, double y, double area)
{
this.name = name;
this.x = x;
this.y = y;
this.area = area;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append(name+" "+x.ToString()+" "+y.ToString()+" "+area.ToString());
return sb.ToString();
}
}
七、页面交互
public Form1()
{
InitializeComponent();
openFile.FileOk += openFile_FileOk;
}
public static List<Point> before=new List<Point>();
public string report = null;
private void toolStripLabel1_Click(object sender, EventArgs e)
{
if (openFile.ShowDialog() == DialogResult.OK)
{
string name=openFile.FileName;
before=Read.Readfile(name);
dataGridView1.RowCount = before.Count;
for(int i = 0; i < before.Count; i++)
{
dataGridView1[0, i].Value = before[i].name;
dataGridView1[1, i].Value = before[i].x;
dataGridView1[2, i].Value = before[i].y;
dataGridView1[3, i].Value = before[i].area;
}
}
}
private void openFile_FileOk(object sender, CancelEventArgs e)
{
}
private void toolStripLabel2_Click(object sender, EventArgs e)
{
report += "1 P6 的坐标 x" + before[5].x.ToString("F3") + "\n";
report += "2 P6 的坐标 y " + before[5].y.ToString("F3") + "\n";
report += "3 P6 的区号" + before[5].area + "\n";
Alspace.Classify();
report += "4 1 区(区号为 1)的事件数量 n1 " + Alspace.ptcode[0].Count+"\n";
report += "5 4 区(区号为 4)的事件数量 n4 " + Alspace.ptcode[3].Count + "\n";
report += "6 6 区(区号为 6)的事件数量 n6 " + Alspace.ptcode[5].Count + "\n";
report += "7 事件总数 n" + before.Count+"\n";
Alspace.Averge(out double avx, out double avy);
report += "8 坐标分量 x 的平均值 X" + avx.ToString("F3") + "\n";
report += "9 坐标分量 y 的平均值Y " + avy.ToString("F3") + "\n";
Alspace.Allcha();
report += "10 P6 坐标分量与平均中心之间的偏移量 a6 " + Read.pts[5].a.ToString("F3") + "\n";
report += "11 P6 坐标分量与平均中心之间的偏移量 b6 " + Read.pts[5].b.ToString("F3") + "\n";
Alspace.Helpword(out double A, out double B, out double C);
report += "12 辅助量 A " + A.ToString("F3") + "\n";
report += "13 辅助量 B " + B.ToString("F3") + "\n";
report += "14 辅助量 C " + C.ToString("F3") + "\n";
Alspace.Sdsigema(out double sigema, out double SDEx, out double SDEy);
report += "15 标准差椭圆长轴与竖直方向的夹角�" + sigema.ToString("F3") + "\n";
report += "16 标准差椭圆的长半轴" + SDEx.ToString("F3") + "\n";
report += "17 标准差椭圆的短半轴" + SDEy.ToString("F3") + "\n";
Alspace.Avcenter(Alspace.ptcode[0], out double x1, out double y1);
Alspace.Avcenter(Alspace.ptcode[3], out double x4, out double y4);
report += "18 1 区平均中心的坐标分量 X" + x1.ToString("F3") + "\n";
report += "19 1 区平均中心的坐标分量 Y" + y1.ToString("F3") + "\n";
report += "20 4 区平均中心的坐标分量 X" + x4.ToString("F3") + "\n";
report += "21 4 区平均中心的坐标分量 Y" + y4.ToString("F3") + "\n";
Alspace.Weight(1, 4, out double w14);
Alspace.Weight(6, 7, out double w67);
report += "22 1 区和 4 区的空间权重w1,4 " + w14.ToString("F6") + "\n";
report += "23 6 区和 7 区的空间权重w6,7 " + w67.ToString("F6") + "\n";
Alspace.Allmoulan(out double avX, out double I, out double S);
report += "24 研究区域犯罪事件的平均值�" + avX.ToString("F6") + "\n";
report += "25 全局莫兰指数辅助量" + S.ToString("F6") + "\n";
report += "26 全局莫兰指数" + I.ToString("F6") + "\n";
Alspace.Portmolan(1,out double I1,out double S1);
Alspace.Portmolan(3, out double I3, out double S3);
Alspace.Portmolan(5, out double I5, out double S5);
Alspace.Portmolan(7, out double I7, out double S7);
report += "27 1 区的局部莫兰指数" + I1.ToString("F6") + "\n";
report += "28 3 区的局部莫兰指数" + I3.ToString("F6") + "\n";
report += "29 5 区的局部莫兰指数" + I5.ToString("F6") + "\n";
report += "30 7 区的局部莫兰指数" + I7.ToString("F6") + "\n";
Alspace.Portpoint(out double miu, out double sigemaa);
report += "31 局部莫兰指数的平均数" + miu.ToString("F6") + "\n";
report += "32 局部莫兰指数的标准差" + sigema.ToString("F6") + "\n";
Alspace.Molan(1, out double Z1);
Alspace.Molan(3, out double Z3);
Alspace.Molan(5, out double Z5);
Alspace.Molan(7, out double Z7);
report += "33 1 区局部莫兰指数的 Z 得分" + Z1.ToString("F6") + "\n";
report += "34 3 区局部莫兰指数的 Z 得分" + Z3.ToString("F6") + "\n";
report += "35 5 区局部莫兰指数的 Z 得分" + Z5.ToString("F6") + "\n";
report += "36 7 区局部莫兰指数的 Z 得分" + Z7.ToString("F6") + "\n";
richTextBox1.Text = report;
}
private void toolStripLabel3_Click(object sender, EventArgs e)
{
Read.Savefile(report);
}
八、页面布局
九、结果
1 P6 的坐标 x92295.323
2 P6 的坐标 y 100520.233
3 P6 的区号4
4 1 区(区号为 1)的事件数量 n1 1408
5 4 区(区号为 4)的事件数量 n4 288
6 6 区(区号为 6)的事件数量 n6 744
7 事件总数 n7754
8 坐标分量 x 的平均值 X95635.466
9 坐标分量 y 的平均值Y 97175.589
10 P6 坐标分量与平均中心之间的偏移量 a6 -3340.143
11 P6 坐标分量与平均中心之间的偏移量 b6 3344.644
12 辅助量 A -501728394.420
13 辅助量 B 60614732934.584
14 辅助量 C -60612656412.248
15 标准差椭圆长轴与竖直方向的夹角 -0.781
16 标准差椭圆的长半轴3954.899
17 标准差椭圆的短半轴94.495
18 1 区平均中心的坐标分量 X95577.112
19 1 区平均中心的坐标分量 Y97233.212
20 4 区平均中心的坐标分量 X95554.001
21 4 区平均中心的坐标分量 Y97263.180
22 1 区和 4 区的空间权重w1,4 0.026424
23 6 区和 7 区的空间权重w6,7 0.003706
24 研究区域犯罪事件的平均值 1107.714286
25 全局莫兰指数辅助量1.019281
26 全局莫兰指数-0.031250
27 1 区的局部莫兰指数-0.046333
28 3 区的局部莫兰指数0.016573
29 5 区的局部莫兰指数0.025204
30 7 区的局部莫兰指数0.026354
31 局部莫兰指数的平均数-0.002412
32 局部莫兰指数的标准差-0.781259
33 1 区局部莫兰指数的 Z 得分-1.360401
34 3 区局部莫兰指数的 Z 得分0.588010
35 5 区局部莫兰指数的 Z 得分0.855335
36 7 区局部莫兰指数的 Z 得分0.890957