我有一个值表,存储在列表列表中,如:
A = [ [a[1],b[1],c[1]],
[a[2],b[2],c[2]],
...
[a[m],b[m],c[m]]]
with
a[i] < b[1]
b[i] < a[i+1]
0 < c[i] < 1
和一个numpy数组,如:
X = [x[1], x[2], ..., x[n]]
我需要创建一个数组
Y = [y[1], y[2], ..., y[n]]
其中Y的每个值都对应
for i in [1,2, ..., n]:
for k in [1,2, ..., m]:
if a[k] < x[i] < b[k]:
y[i] = c[k]
else:
y[i] = 1
请注意X和Y的长度相同,但A完全不同。 Y可以取A的第三列中的任何值(对于k = 1,2,... m,c [k]),只要a [k] <1。 x [i]&lt;满足b [k](对于k = 1,2,... m和对于i = 1,2,... n)。
在我正在处理的实际案例中,n = 6789,m = 6172。
我可以使用嵌套的“for”循环进行验证,但它确实很慢。实现这一目标的最快方法是什么?如果X和Y在哪里有2D numpy数组呢?
示例数据:
a = [10, 20, 30, 40, 50, 60, 70, 80, 90]
b = [11, 21, 31, 41, 51, 61, 71, 81, 91]
c = [ 0.917, 0.572, 0.993 , 0.131, 0.44, 0.252 , 0.005, 0.375, 0.341]
A = A = [[d,e,f] for d,e,f in zip(a,b,c)]
X = [1, 4, 10.2, 20.5, 25, 32, 41.3, 50.5, 73]
预期成果:
Y = [1, 1, 0.993, 0.132, 1, 1, 1, 0.375, 1 ]
答案 0 :(得分:1)
方法#1:使用与broadcasting
的强力比较 -
import numpy as np
# Convert to numpy arrays
A_arr = np.array(A)
X_arr = np.array(X)
# Mask that represents "if a[k] < x[i] < b[k]:" for all i,k
mask = (A_arr[:,None,0]<X_arr) & (X_arr<A_arr[:,None,1])
# Get indices where the mask has 1s, i.e. the conditionals were satisfied
_,C = np.where(mask)
# Setup output numpy array and set values in it from third column of A
# that has conditionals satisfied for specific indices
Y = np.ones_like(X_arr)
Y[C] = A_arr[C,2]
方法#2:基于与np.searchsorted
-
import numpy as np
# Convert A to 2D numpy array
A_arr = np.asarray(A)
# Setup intervals for binning later on
intv = A_arr[:,:2].ravel()
# Perform binning & get interval & grouped indices for each X
intv_idx = np.searchsorted(intv, X, side='right')
grp_intv_idx = np.floor(intv_idx/2).astype(int)
# Get mask of valid indices, i.e. X elements are within grouped intervals
mask = np.fmod(intv_idx,2)==1
# Setup output array
Y = np.ones(len(X))
# Extract col-3 elements with grouped indices and valid ones from mask
Y[mask] = A_arr[:,2][grp_intv_idx[mask]]
# Remove (set to 1's) elements that fall exactly on bin boundaries
Y[np.in1d(X,intv)] = 1
请注意,如果您需要输出作为列表,您可以将numpy数组转换为带有这样的调用的列表 - Y.tolist()
。
示例运行 -
In [480]: A
Out[480]:
[[139.0, 355.0, 0.5047342078960846],
[419.0, 476.0, 0.3593886192040009],
[580.0, 733.0, 0.3137694021600973]]
In [481]: X
Out[481]: [555, 689, 387, 617, 151, 149, 452]
In [482]: Y
Out[482]:
array([ 1. , 0.3137694 , 1. , 0.3137694 , 0.50473421,
0.50473421, 0.35938862])
答案 1 :(得分:0)
使用1-d阵列时,它并不太糟糕:
a,b,c = np.array(A).T
mask = (a<x) & (x<b)
y = np.ones_like(x)
y[mask] = c[mask]
如果x
和y
维度较高,那么您的A
矩阵也需要更大。但基本概念的作用相同。