i have a 2D array numpy s like this:
s = np.array([[ 5., 4., np.nan, 1., np.nan],
[np.nan, 4., 4., 2., 2.],
[ 3., np.nan, np.nan, 5., 5.],
[np.nan, 3., 4., 4., np.nan]])
#now i want to create a new np array s1 base on s like this
s1= np.empty((len(s),len(s)))
for i in range(len(s)):
a = np.abs(s - s[i])
a = np.nanmean(a, axis=1)
w = 1 / (a 0.001)
s1[i] = w
s1
array([[1000. , 1.99600798, 0.33322226, 0.49975012],
[ 1.99600798, 1000. , 0.33322226, 0.999001 ],
[ 0.33322226, 0.33322226, 1000. , 0.999001 ],
[ 0.49975012, 0.999001 , 0.999001 , 1000. ]])
#without use for loop i write like this
def f(x,y):
a = np.abs(s[y]-s[x])
a = np.nanmean(a)
if np.isnan(a):
return 0
w = 1/(a 0.001) #not let 1/0
return w
s1 = np.fromfunction(np.vectorize(f),(len(s),len(s)),dtype='int')
s1
array([[1000. , 1.99600798, 0.33322226, 0.49975012],
[ 1.99600798, 1000. , 0.33322226, 0.999001 ],
[ 0.33322226, 0.33322226, 1000. , 0.999001 ],
[ 0.49975012, 0.999001 , 0.999001 , 1000. ]])
First i want to ask is my np.fromfunction right? Second, are there another ways to rewrite this code with numpy without use for loop?
CodePudding user response:
What about
>>> 1/(
1e-3 np.nanmean(
np.abs(s - s[:, None,:]),
axis=2
)
)
array([[1.00000000e 03, 1.99600798e 00, 3.33222259e-01, 4.99750125e-01],
[1.99600798e 00, 1.00000000e 03, 3.33222259e-01, 9.99000999e-01],
[3.33222259e-01, 3.33222259e-01, 1.00000000e 03, 9.99000999e-01],
[4.99750125e-01, 9.99000999e-01, 9.99000999e-01, 1.00000000e 03]])
Or in a fully numpy-idiomatic fashion
>>> np.reciprocal(1e-3 np.nanmean(np.abs(s - s[:, np.newaxis, :]), axis=2))
array([[1.00000000e 03, 1.99600798e 00, 3.33222259e-01, 4.99750125e-01],
[1.99600798e 00, 1.00000000e 03, 3.33222259e-01, 9.99000999e-01],
[3.33222259e-01, 3.33222259e-01, 1.00000000e 03, 9.99000999e-01],
[4.99750125e-01, 9.99000999e-01, 9.99000999e-01, 1.00000000e 03]])
where, as of December 2021, np.newaxis
is None
.
CodePudding user response:
You may be looking for a pure numpy solution:
repeat_s_by_array = np.repeat(s[np.newaxis,:,:], repeats=len(s), axis=0)
repeat_s_by_rows = np.repeat(s, repeats=len(s), axis=0).reshape(len(s),len(s),-1)
abs_vals = np.abs(repeat_s_by_array - repeat_s_by_rows)
mean = np.nanmean(abs_vals, axis=-1)
s1 = 1 / (mean 0.001)
Or you can do a one-liner:
s1 = 1 / (np.array([np.nanmean(np.abs(s - s[i]), axis=1) for i in range(len(s))]) 0.001)