Joh*_*mid 7 python arrays raster fill
我使用Python并拥有一个值为1.0,2.0,3.0,4.0,5.0,6.0和np.nan作为NoData的数组.
我想用一个值填充所有"nan".该值应该是周围值的大部分.
例如:
1 1 1 1 1
1 n 1 2 2
1 3 3 2 1
1 3 2 3 1
Run Code Online (Sandbox Code Playgroud)
在该示例中,"n"将呈现"nan".其大多数邻居的值为1.因此,"nan"将被值1替换.
注意,由"nan"组成的孔的尺寸可以是1到5.例如(最大尺寸为5纳米):
1 1 1 1 1
1 n n n 2
1 n n 2 1
1 3 2 3 1
Run Code Online (Sandbox Code Playgroud)
这里"nan"的洞有以下周围的值:
surrounding_values = [1,1,1,1,1,2,1,2,3,2,3,1,1,1] -> Majority = 1
Run Code Online (Sandbox Code Playgroud)
我尝试了以下代码:
from sklearn.preprocessing import Imputer
array = np.array(.......) #consisting of 1.0-6.0 & np.nan
imp = Imputer(strategy="most_frequent")
fill = imp.fit_transform(array)
Run Code Online (Sandbox Code Playgroud)
这非常好用.但是,它只使用一个轴(0 =列,1 =行).默认值为0(列),因此它使用同一列的大多数周围值.例如:
Array
2 1 2 1 1
2 n 2 2 2
2 1 2 2 1
1 3 2 3 1
Filled Array
2 1 2 1 1
2 1 2 2 2
2 1 2 2 1
1 3 2 3 1
Run Code Online (Sandbox Code Playgroud)
所以在这里你可以看到,虽然大多数是2,但是大多数周围的列值都是1,因此它变为1而不是2.
因此,我需要使用python找到另一种方法.有什么建议或想法吗?
补充:
在我添加了Martin Valgur非常有帮助的改进后,你会看到结果.
将"0"视为海(蓝色),将其他值(> 0)视为陆地(红色).
如果有一个被陆地包围的"小"海(海洋的大小可以再次为1-5 px),那么它将获得陆地,因为您可以在结果图像中成功查看.如果被包围的海域大于5px或在陆地之外,海洋将不会获得土地(这在图像中是不可见的,因为事实并非如此).
如果有1px"nan",其中大部分海洋比陆地多,它仍将成为陆地(在这个例子中它有50/50).
下图显示了我的需求.在海(value = 0)和land(值> 0)之间的边界处,"nan"像素需要获得大部分地值的值.
这听起来很难,我希望我能够生动地解释它.
label()使用和binary_dilation()from的可能解决方案scipy.ndimage:
import numpy as np
from scipy.ndimage import label, binary_dilation
from collections import Counter
def impute(arr):
imputed_array = np.copy(arr)
mask = np.isnan(arr)
labels, count = label(mask)
for idx in range(1, count + 1):
hole = labels == idx
surrounding_values = arr[binary_dilation(hole) & ~hole]
most_frequent = Counter(surrounding_values).most_common(1)[0][0]
imputed_array[hole] = most_frequent
return imputed_array
Run Code Online (Sandbox Code Playgroud)
编辑:关于松散相关的后续问题,您可以扩展上面的代码来实现您所追求的目标:
import numpy as np
from scipy.ndimage import label, binary_dilation, binary_closing
def fill_land(arr):
output = np.copy(arr)
# Fill NaN-s
mask = np.isnan(arr)
labels, count = label(mask)
for idx in range(1, count + 1):
hole = labels == idx
surrounding_values = arr[binary_dilation(hole) & ~hole]
output[hole] = any(surrounding_values)
# Fill lakes
land = output.astype(bool)
lakes = binary_closing(land) & ~land
labels, count = label(lakes)
for idx in range(1, count + 1):
lake = labels == idx
output[lake] = lake.sum() < 6
return output
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1053 次 |
| 最近记录: |