【问题标题】:Fill 2D numpy array from three 1D numpy arrays从三个 1D numpy 数组填充 2D numpy 数组
【发布时间】:2013-02-27 17:55:22
【问题描述】:

是否有一种有效的方法可以在不使用循环的情况下从未排序的坐标点(即并非所有的经纬度和/或纬度都升序或降序)创建二维数组?

示例数据

lats = np.array([45.5,45.5,45.5,65.3,65.3,65.3,43.2,43.2,43.2,65.3])
lons = np.array([102.5,5.5,116.2,102.5,5.5,116.2,102.5,5.5,116.2,100])
vals = np.array([3,4,5,6,7,7,9,1,0,4])

示例输出
每列代表一个唯一的经度(102.5、5.5、116.2 和 100),每列代表一个唯一的纬度(45.5、65.3 和 43.2)。

([ 3, 4, 5, NaN],
 [ 6, 7, 7, 4],
 [ 9, 1, 0, NaN])

不过,这并不是那么简单,因为我不一定知道每个 lon 或 lat 有多少个重复项,这决定了数组的形状。

更新:
我的问题的数据排列不正确。我现在已经安排好了,所以它们都是唯一的对,还有一个额外的数据点来演示当存在 NaN 时应该如何安排数据。

【问题讨论】:

  • 什么决定了输出数组的大小? latslons 中非重复值的数量?
  • 没错……我想:)
  • 您能用文字解释使示例输出所需答案的规范吗?当 100 不是 vals 中的值时,指示应将 100 放在输出中的逻辑是什么?为什么会有?
  • 那只是一个错误,我很抱歉。它应该是我没有放入值数组的一个附加值。现在更正。

标签: python numpy


【解决方案1】:

您发布的示例几乎没有意义,并且不允许任何合理的方式来指定丢失的数据。我在这里猜测,但您可能正在处理的唯一合理的事情似乎是这样的:

>>> lats = np.array([43.2, 43.2, 43.2, 45.5, 45.5, 45.5, 65.3, 65.3, 65.3])
>>> lons = np.array([5.5, 102.5, 116.2, 5.5, 102.5, 116.2, 5.5, 102.5, 116.2])
>>> vals = np.array([3, 4, 5, 6, 7, 7, 9, 1, 0])

vals[j] 中的值来自纬度lats[j] 和经度lons[j],但数据可能会打乱,如下所示:

>>> indices = np.arange(9)
>>> np.random.shuffle(indices)
>>> lats = lats[indices]
>>> lons = lons[indices]
>>> vals = vals[indices]
>>> lats
array([ 45.5,  43.2,  65.3,  45.5,  43.2,  65.3,  45.5,  65.3,  43.2])
>>> lons
array([   5.5,  116.2,  102.5,  116.2,    5.5,  116.2,  102.5,    5.5,  102.5])
>>> vals
array([6, 5, 1, 7, 3, 0, 7, 9, 4])

你可以把它排列成一个数组,如下所示:

>>> lat_vals, lat_idx = np.unique(lats, return_inverse=True)
>>> lon_vals, lon_idx = np.unique(lons, return_inverse=True)
>>> vals_array = np.empty(lat_vals.shape + lon_vals.shape)
>>> vals_array.fill(np.nan) # or whatever yor desired missing data flag is
>>> vals_array[lat_idx, lon_idx] = vals
>>> vals_array
array([[ 3.,  4.,  5.],
       [ 6.,  7.,  7.],
       [ 9.,  1.,  0.]])

【讨论】:

  • 谢谢詹姆。这也是一个很好的答案,非常有帮助。我为这个可怜的例子道歉。我发现有时很难在不添加不必要的内容来混淆事物的情况下完善我的问题。
  • 我想我明白了事情没有意义的地方。 lat/lon/value 数据应该是唯一的对,并且它们的顺序都是一致的;但是,没有一个列表是严格按照升序或降序排列的。我已经正确地对事物进行了重新排序(因此它们是唯一的)并添加了一个值来演示存在 NaN 时的输出应该如何。感谢您的帮助!
  • @shootingstars 您编辑的样本输入仍然与您的预期输出不一致。但我现在更加确信,我上面提出的就是你想要的。在您的示例输入上尝试(在将100 附加到vals 数组之后!),看看你得到了什么,理解为什么它与你所期望的不同,我想你最终会意识到上述方法是正确的去。
  • 是的,效果非常好,而且看起来比使用视图更清晰。我的输出数组中的100 和我的vals 数组中缺少新值是键盘错误:) 抱歉我的误解和拼写错误,再次感谢您的帮助!这很有启发性。
  • 谢谢 Jaime,我花了好几个小时寻找这样的解决方案!
【解决方案2】:

如果您要创建二维数组,则所有数组都必须具有相同数量的点。如果这是真的,你可以简单地做

out = np.vstack((lats, lons, vals))

编辑

认为这可能是你所追求的,它至少符合你的问题:)

xsize = len(np.unique(lats))
ysize = len(np.unique(lons))

然后如果你的数据表现得很好

out = [vals[i] for i, (x, y) in enumerate(zip(lats, lons))]
out = np.asarray(out).reshape((xsize, ysize))

【讨论】:

  • 我认为我的措辞很糟糕,但我想最终得到一个维度数组 (len(lats), len(lon)),其中仅包含它们各自坐标的值。
  • 但是 latslons 不是整数值 - 所以它们不能整齐地放入大小为 (max(lats), max(lon)) 的网格中,我错过了什么吗?
  • 对不起,这些是列表,所以它将是列表的长度(即元素的整数),但我刚刚意识到我真正想要的是 len(lats)/重复 lats 的数量等。请参阅我对问题的更新。
【解决方案3】:
import numpy as np

lats = np.array([45.5,45.5,45.5,65.3,65.3,65.3,43.2,43.2,43.2,65.3])
lons = np.array([102.5,5.5,116.2,102.5,5.5,116.2,102.5,5.5,116.2,100])
vals = np.array([3,4,5,6,7,7,9,1,0,4])


def unique_order(seq): 
    # http://www.peterbe.com/plog/uniqifiers-benchmark (Dave Kirby)
    # Order preserving
    seen = set()
    return [x for x in seq if x not in seen and not seen.add(x)]

unique_lats, idx_lats = np.unique(lats, return_inverse=True)
unique_lons, idx_lons = np.unique(lons, return_inverse=True)
perm_lats = np.argsort(unique_order(lats))
perm_lons = np.argsort(unique_order(lons))

result = np.empty((len(unique_lats), len(unique_lons)))
result.fill(np.nan)
result[perm_lats[idx_lats], perm_lons[idx_lons]] = vals
print(result)

产量

[[  3.   4.   5.  nan]
 [  6.   7.   7.   4.]
 [  9.   1.   0.  nan]]

【讨论】:

  • 这看起来不错,但我不断收到ValueError: total size of new array must be unchanged。我猜我在某处混淆了一些东西,因为这和 danodonovan 的答案都很直截了当。
  • 另外,你在输出上是对的。我遇到的错误是当我将它与我的实际数据集/脚本一起使用时,而不是示例。
  • ValueError 表示len(vals) 不等于len(np.unique(lats)) * len(np.unique(lons))。如果len(vals) 太长,是否要截断vals?如果len(vals) 太短,你想用0s 填充数组的其余部分吗?还有很多其他的可能性......
  • 啊...我看到我的 lats 的独特性比 lons 少(都是独特的)。我想我想用缺失值(例如 NaN 或 -9999 或任何合适的值)填充其余部分。
  • 您是否有建议的填补空白的方法?看来reshape 不直接支持这个。
猜你喜欢
  • 1970-01-01
  • 2020-11-05
  • 2017-06-18
  • 1970-01-01
  • 2022-09-23
  • 2013-08-28
  • 1970-01-01
  • 2021-08-15
  • 2021-01-28
相关资源
最近更新 更多