我希望从数组3 * 4中删除最高数字和最低数字。比方说,数据看起来像这样:
a=np.array([[1,4,5,10],[2,6,5,0],[3,9,9,0]])
所以我希望看到这样的结果: deleted_data = [4,5],[2,5],[3]
你能告诉我如何删除每个阵列的最大值和最小值吗?
这样做,我确实喜欢这个(更新):
#to find out the max / min values:
b = np.max(a,1) #max
c = np.min(a,1) #min
#creating dataset after deleting max & min
d=(a!=b[:,None]) & (a!=c[:,None])
f=[i[j] for i,j in zip(a, d)]
output: [array([8, 7, 7, 9, 9, 8]), array([8, 7, 8, 6, 8, 8]), array([9, 8, 9, 9, 8]), array([6, 7, 7, 6, 6, 7]), array([7, 7, 7, 7, 6])]
现在我不确定如何计算列表对象的平均值? 我想计算每个数组的平均值,所以我试过这个:
mean1=f.mean(axis=0)
但它不起作用。
答案 0 :(得分:2)
另一种方法是使用Masked Array
import numpy.ma as ma
mask = np.logical_or(a == a.max(1, keepdims = 1), a == a.min(1, keepdims = 1))
a_masked = ma.masked_array(a, mask = mask)
如果你想要平均的非掩盖元素,你可以从那里
a_masked.mean()
或者你甚至可以做行的意思
a_masked.mean(1).data
或列(奇怪,但似乎是你要求的)
a_masked.mean(0).data
答案 1 :(得分:1)
python list
有一个remove
方法。
使用效用函数,我们可以从行中删除min和max元素:
def foo(i,j,k):
il = i.tolist()
il.remove(j)
il.remove(k)
return il
In [230]: [foo(i,j,k) for i,j,k in zip(a,b,c)]
Out[230]: [[4, 5], [2, 5], [3, 9]]
这可以转回到np.array(...)
的数组中。请注意,这只删除了最后一行中的9
之一。如果它已经删除了两个,则最后一个列表只有1个值,结果无法转回到2d数组。
我确信我们可以提出一种纯数组方法,可能使用argmax
和argmin
代替max
和min
。但我认为列表方法对于Python初学者来说是一个更好的起点。
数组屏蔽方法
In [232]: bi = np.argmax(a,1)
In [233]: ci = np.argmin(a,1)
In [234]: bi
Out[234]: array([3, 1, 1], dtype=int32)
In [235]: ci
Out[235]: array([0, 3, 3], dtype=int32)
In [243]: mask = np.ones_like(a, bool)
In [244]: mask[np.arange(3),bi]=False
In [245]: mask[np.arange(3),ci]=False
In [246]: mask
Out[246]:
array([[False, True, True, False],
[ True, False, True, False],
[ True, False, True, False]], dtype=bool)
In [247]: a[mask]
Out[247]: array([4, 5, 2, 5, 3, 9])
In [248]: _.reshape(3,-1)
Out[248]:
array([[4, 5],
[2, 5],
[3, 9]])
如果我们只是从每一行删除一个最多和一分钟,这样做会更好。
另一种掩盖方法:
In [257]: (a!=b[:,None]) & (a!=c[:,None])
Out[257]:
array([[False, True, True, False],
[ True, False, True, False],
[ True, False, False, False]], dtype=bool)
In [258]: a[(a!=b[:,None]) & (a!=c[:,None])]
Out[258]: array([4, 5, 2, 5, 3])
这会删除最后一行中的所有	 9。但它不会保留行拆分。
这会保留行结构,并允许可变长度:
In [259]: mask=(a!=b[:,None]) & (a!=c[:,None])
In [260]: [i[j] for i,j in zip(a, mask)]
Out[260]: [array([4, 5]), array([2, 5]), array([3])]
答案 2 :(得分:1)
正如@hpaulj预测的那样,有一种仅限数组的方法。这是一个很糟糕的事情。作为一个单行:
a[np.arange(a.shape[0])[:, None], np.sort(np.argpartition(a, (0,-1), axis = 1)[:, 1:-1], axis = 1)]
让我们打破这一点:
y_ = np.argpartition(a, (0,-1), axis = 1)[:, 1:-1]
argpartiton
获取每行的0
(最小)和-1
(最大)元素的索引,并将它们重新移动到第一个和最后一个位置。 [:,1:-1]
为其他所有内容编制索引。现在argpartition
有时可以重新排序其余元素,所以
y = np.sort(y_ , axis = 1)
我们将其余指数分类回原点位置。现在,我们为您的原始y.shape -> (m, n-2)
数组添加了(m, n) = a.shape
索引数组,其中删除了最大值和最小值。
现在使用它,我们也需要行指示。
x = np.arange(a.shape[0])[:, None]
arange
只提供m
行索引。要将此x.shape -> (a.shape[0],) -> (m,)
数组广播到索引数组,您需要[:, None]
来制作x.shape -> (m, 1)
。现在m
排队进行广播,你有两套索引。
a[x, y]
array([[4, 5],
[2, 5],
[3, 9]])
答案 3 :(得分:1)
您可以通过屏蔽的两个步骤到达每行不是max
或min
的元素的平均最终目的地 -
In [140]: a # input array
Out[140]:
array([[ 1, 4, 5, 10],
[ 2, 6, 5, 0],
[ 3, 9, 9, 0]])
In [141]: m = (a!=a.min(1,keepdims=1)) & (a!=a.max(1,keepdims=1))
In [142]: (a*m).sum(1)/m.sum(1).astype(float)
Out[142]: array([ 4.5, 3.5, 3. ])
这避免了创建中间参差不齐的数组的麻烦,这些数组不是使用NumPy函数操作的最方便的数据格式。
或者,为了提升效果,请使用np.einsum
来获得与(a*m).sum(1)
同等的np.einsum('ij,ij->i',a,m)
。
更大阵列上的运行时测试 -
In [181]: np.random.seed(0)
In [182]: a = np.random.randint(0,10,(5000,5000))
# @Daniel F' soln from https://stackoverflow.com/a/47325431/
In [183]: %%timeit
...: mask = np.logical_or(a == a.max(1, keepdims = 1), a == a.min(1, keepdims = 1))
...: a_masked = ma.masked_array(a, mask = mask)
...: out = a_masked.mean(1).data
1 loop, best of 3: 251 ms per loop
# Posted in here
In [184]: %%timeit
...: m = (a!=a.min(1,keepdims=1)) & (a!=a.max(1,keepdims=1))
...: out = (a*m).sum(1)/m.sum(1).astype(float)
10 loops, best of 3: 165 ms per loop
# Posted in here with additional einsum
In [185]: %%timeit
...: m = (a!=a.min(1,keepdims=1)) & (a!=a.max(1,keepdims=1))
...: out = np.einsum('ij,ij->i',a,m)/m.sum(1).astype(float)
10 loops, best of 3: 124 ms per loop
答案 4 :(得分:0)
如果问题是要从numpy数组arr
中删除最小和/或最大元素,那么我认为这是最简单的方法。
np.delete(arr, np.argmax(arr))
示例
tmp = np.random.random(3)
print(tmp)
tmp = np.delete(tmp, np.argmax(tmp))
print(tmp)
返回
[0.7366768 0.65492774 0.93632866]
[0.7366768 0.65492774]