0

我正在尝试将一个文件中的经纬度位置解析为另一个文件中的几个命名字段。

我有一个文件是这样的..

                 f1--f2--f3--------f4--------                f5---
 R               20175155 41273951N078593973W                18012              
 R               20175156 41274168N078593975W                18000              
 R               20175157 41274387N078593976W                17999              
 R               20175158 41274603N078593977W                18024              
 R               20175159 41274823N078593978W                18087   

每个字符都在一个特定的位置,所以我需要根据字符定义字段。

f1 字符 18-21; f2 字符 22 - 25; f3 字符 26-35;f4 字符 36-45;f5 字符 62-66。

我有另一个更大的 csv 文件,其中包含对应于 f3、f4、f5 的字段 11、12 和 13。

awk -F',' '{print $11, $12, $13}'
41.46703821 -078.98476926 519.21
41.46763555 -078.98477791 524.13
41.46824123 -078.98479015 526.67
41.46884129 -078.98480615 528.66
41.46943371 -078.98478482 530.50

我需要在文件 2 字段 11 && 12 中找到与文件 1 字段 1 && 2 最接近的匹配项;

当找到最接近的匹配项时,我需要将文件 1 中的字段 1、2、3、4、5 插入文件 2 字段 16、17、18、19、20。

如您所见,格式略有不同。文件1像这样分解..

文件 1

f3-------f4--------

DDMMSSdd DDDMMSSdd 

41273951N078593973W

文件 2

f11-------- f12---------

DD dddddddd  DDD dddddddd

41.46703821 -078.98476926

N 表示 f3 为正数,W 表示 f4 为负数。

我用 sed 更改了文件 1,可笑的一个衬里效果很好.. (更好的方法???)

cat $file1 |sed 's/.\{17\}//' |sed 's/\(.\{4\}\)\(.\{4\}\)\(.\{9\}\)\(.\)\(.\{9\}\)\(.\)\(.\{16\}\)\(.\{5\}\)/\1,\2,\3,\4,\5,\6,\8/'|sed 's/\(.\{10\}\)\(.\{3\}\)\(.\{2\}\)\(.\{2\}\)\(.\{2\}\)\(.\{3\}\)\(.\{3\}\)\(.\{2\}\)\(.*\)/\1\2,\3,\4.\5\6\7,\8\9/'|sed 's/\(.\{31\}\)\(.\{2\}\)\(.*\)/\1,\2.\3/'

2017,5155, 41,27,39.51,N,078,59,39.73,W,18012
2017,5156, 41,27,41.68,N,078,59,39.75,W,18000
2017,5157, 41,27, 43.87,N,078,59,39.76,W,17999
2017,5158, 41,27,46.03,N,078,59,39.77,W,18024
2017,5159, 41,27,48.23,N,078,59, 39.78,W,18087

现在我必须转换格式.. (解决了这个(见下文)--问题--数字四舍五入太远了。我需要至少有六个小数位。)

awk -F',' '{for (i=1;i<=NF;i++) {if (i <= 2) printf ($i","); else if (i == 3&&$6 == "S") printf("-"$3+($4/60)+($5/3600)","); else if (i == 3&&$6 == "N") printf($3+($4/60)+($5/3600)","); else if (i == 7&&$10 == "W") printf("-"$7+($8/60)+($9/3600)","); else if (i == 7&&$10 == "E") printf($7+($8/60)+($9/3600)","); if (i == 11) printf ($i"\n")}}'

2017,5155,41.461, -78.9944,18012 2017,5156,41.4616
, -78.9944,18000


这就是我所在的地方。

解决了这个 *我需要从这个公式中得到至少有 6 个小数位的数字格式。*

printf($3+($4/60)+($5/3600)) 添加了“%.8f”

printf("%.8f", $3+($4/60)+($5/3600))

下一个问题是将字段文件 1 f3 和 f4 与文件 2 f11 和 f12 中最接近的匹配项进行匹配。

有任何想法吗?

然后我需要计算字段之间的距离。

在 Excel 中,公式将是这样的..

=ATAN2(COS(lat1)*SIN(lat2)-SIN(lat1)*COS(lat2)*COS(lon2-lon1), SIN(lon2-lon1)*COS(lat2)) 

我可以用什么来计算?

*更新---我正在寻找匹配位置的短距离。我正在考虑将诸如毕达哥拉斯定理之类的简单方法应用于最接近的匹配。甚至可能使用更少的小数位。它必须快很多倍。也许是这样的.. *

x = (lon2-lon1) * Math.cos((lat1+lat2)/2);

y = (lat2-lat1);

d = Math.sqrt(x*x + y*y) * R;

然后我可以在最终文件更新后进行更准确的大量计算。

谢谢

4

1 回答 1

0

执行最接近匹配后无法进行距离计算:最接近是通过比较距离值定义的。awk 可以评估您想要的公式(看起来像大圆距离?)。看看这一章,看看你需要什么。

最大的问题是找到最近的匹配。编写一个 awk 脚本,该脚本采用文件 1 的单行并输出文件 2 中的行和一个额外的列。该列是根据您的距离公式计算一对点之间的距离。如果您按数字 ( sort -n) 对该文件进行排序,那么最接近的匹配项位于顶部。然后你需要一个循环遍历文件 1 中每一行的脚本,调用你的 awk 脚本,用来head -n1提取最接近的匹配,然后以你想要的格式输出。

这在 bash 和 awk 中都是可能的,但在 Python 中它会是一个更简单的脚本。取决于你喜欢哪个。

于 2012-07-08T09:34:52.733 回答