我有一组栅格(总共8个),每个栅格每个栅格包含一个1或0。每个栅格代表不同年份的数据。对于第1年到第8年的论证。一组栅格(所有年份)。
我想为每个像元找出最长的连续1。
因此,例如,整个网格可能会为单个单元格记录一个值,例如5,但是在8个网格中,该单元格的最大连续数1等于3。或者另一种表示方式是3年以来,像元是1,然后它开始在零和一之间振荡。
我的栅格处理技能不如矢量处理技能那么热,我对ESRI帮助有很好的了解文件,但我不知道使用现成的地理处理工具将如何实现?
有什么想法吗?
#1 楼
因为这是本地操作,所以让我们弄清楚如何对单个像元进行处理:地图代数将处理其余部分。首先请注意,栅格的顺序显然很重要。因此,单次单元格统计信息(例如单元格总和)将无法执行。
如果在给定单元格上遇到诸如01110101之类的序列,则需要从头到尾处理和
计数从零开始。
每次保存1时递增计数。
保存后,每次遇到0时复位计数。最后一个计数。
最后,获取最大的保存计数(包括最终计数)。
第1步使用恒定零网格实现。步骤2和3取决于我们遇到的情况:因此这是一个有条件的操作。步骤4显然是局部最大值。然后,我们将其更正式地编码为:
count = 0
result = 0
For each value:
If (value==1):
count=count+1
else
result = max(result, count)
count=0
result = max(result, count)
当网格很多时,最好用Python脚本完成,但是有了8个网格就不会繁琐展开循环并手动写出步骤。这揭示了一个小问题:
result=max(longest,count)
有点“副作用”,很难使用光栅操作进行编码。 (但是可以这样做,如下面的第二个解决方案所示。)它的效率也不高,因为它在每个步骤都增加了额外的计算量。因此,我们对方法进行了一些修改,目的是将max
操作推迟到最后。这将需要在每个阶段保存单独的计数。在执行此过程时,我还找到了第一步的快捷方式。这将导致以下解决方案,尽管该解决方案比较长且占用大量RAM,但它很简单并且涉及到快速执行的步骤:
result1 = "grid1"
result2 = con("grid2"==1, "result1"+1, 0)
result3 = con("grid3"==1, "result2"+1, 0)
result4 = con("grid4"==1, "result3"+1, 0)
result5 = con("grid5"==1, "result4"+1, 0)
result6 = con("grid6"==1, "result5"+1, 0)
result7 = con("grid7"==1, "result6"+1, 0)
result8 = con("grid8"==1, "result7"+1, 0)
CellStatistics(["result1", "result2", "result3", "result4", "result5", "result6", "result7" "result8"], "max")
实际语法随您的版本而异ArcMap。 (例如,我相信
CellStatistics
是版本10的新功能,但是始终可以使用本地最大操作。)在具有输入01110101的示例中,“结果*”网格的序列将包含值0、1、2、3、0、1、0、1,因此最后
CellStatistics
将返回3,即最长字符串的长度如果RAM不足,则可以修改解决方案以重新使用中间结果,而执行时间大约会加倍:
result = "grid1"
temp = con("grid2"==1, "result"+1, 0)
result = CellStatistics[["temp", "result"], "max"]
temp = con("grid3"==1, "temp"+1, 0)
result = CellStatistics[["temp", "result"], "max"]
...
temp = con("grid8"==1, "temp"+1, 0)
CellStatistics[["temp", "result"], "max"]
在具有输入01110101的示例中,第一行之后以及每对(“ Con”,“ CellStatistics”)操作之后的(“ temp”,“ result”)值将为(NoData,0)值将是(1、1),(2、2),(3、3),(0、3),(1、3),(0、3),(1、3)。最终值再次为3。
这两种解决方案中的Map Algebra表达式的规则模式都指示如何在脚本中将算法编码为循环,并在每次迭代时适当地更改索引。 >
评论
类型代码块中可能有错字:count = count = 1可能应该是count = count + 1
–MLowry
2012年6月14日19:25
@ML谢谢(眼睛很好!):现在已修复。很难使伪代码绝对正确。人工检查是发现错误的真正资产。另外,尽管我没有在ArcGIS中测试解决方案,但确实在R中实现了第一个解决方案,因此我可以肯定这种方法是正确的。
– hu
2012年6月14日20:33
“威伯”又是你认识的人!如果您被公车撞倒,上帝会帮助我们其余的人!您最初使用Python的方法是我一直在思考的方向,但是我知道使用栅格通常可以完成您已经证明的所有操作。如果您发现自己在英国,将很荣幸为您买一品脱最好的室温扁平啤酒! :)
–Hornbydd
2012年6月15日9:46
谢谢,邓肯:但是请查看Andy Harfoot的出色解决方案!
– hu
2012年6月15日12:19
#2 楼
只是聊一聊,想知道是否可以通过将输入网格视为二进制流来解决该问题。这样一来,您就可以将它们组合起来,从而为序列提供唯一的摘要整数,即01110101 =117。然后可以将该值重新分类,以给出最大的连续1s数。组合八个网格的方式:2*(2*(2*(2*(2*(2*(2*"g8" + "g7") + "g6") + "g5") + "g4") + "g3") + "g2") + "g1"
按位操作也可以按此步骤使用。或者,您可以使用合并,然后进行字段计算。 (字段计算将具有与上一个表达式类似的表达式。)
重分类表必须提供00000000B = 0到11111111B = 255之间的所有值的最大游程长度。 :
0, 1, 1, 2, 1, 1, 2, 3, 1, 1, 1, 2, 2, 2, 3, 4, 1, 1, 1, 2, 1, 1, 2, 3, 2, 2, 2, 2, 3, 3, 4, 5, 1, 1, 1, 2, 1, 1, 2, 3, 1, 1, 1, 2, 2, 2, 3, 4, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 5, 6, 1, 1, 1, 2, 1, 1, 2, 3, 1, 1, 1, 2, 2, 2, 3, 4, 1, 1, 1, 2, 1, 1, 2, 3, 2, 2, 2, 2, 3, 3, 4, 5, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7, 1, 1, 1, 2, 1, 1, 2, 3, 1, 1, 1, 2, 2, 2, 3, 4, 1, 1, 1, 2, 1, 1, 2, 3, 2, 2, 2, 2, 3, 3, 4, 5, 1, 1, 1, 2, 1, 1, 2, 3, 1, 1, 1, 2, 2, 2, 3, 4, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 5, 6, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 4, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 3, 4, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8
此方法在ArcGIS中仅限于约20个网格:使用更多方法可以创建笨拙的属性表。 (
Combine
特别限于20个网格。)评论
+1:这是一个非常好的主意。 (唯一的限制是,当涉及到31个以上的网格时,您将用尽所有的位。)我已经自由地将您的想法充实了一点,以便其他人可以看到实现起来有多么容易。
– hu
2012年6月15日11:59
#3 楼
您是否考虑过将值从0和1更改为2的幂(1,2,4,8,16,32)。当您将8个网格合并在一起时,您将获得每个单元格的唯一值,这将为您提供连续的信息(即:值3表示1年和2年,其中值54表示6至8年)。只是一个想法
评论
这正是@Andy Harfoot几个小时前建议的,Ryan。 :-)
– hu
2012年6月15日12:18
谢谢,抱歉。度假时,我在手机上阅读了此内容。
–瑞安·加内特(Ryan Garnett)
2012年6月15日下午13:16
评论
这实际上是一个很酷的分析。与往常一样,有多种方法可以完成您想做的事情。我认为您需要进行一些编程才能遍历所有组合。一般评论(受@MLowry的此评论启发):请在问题有趣或清晰表达时对问题进行投票。好的问题驱动着我们网站上的一切;请尽我们所能来奖励那些问他们的人!