假设我有一个元组列表,如下所示:
list = [(a,1), (b,3), (c,5)]
我的目标是获取元组列表中值的第一个元素,使用元组的第二个元素。在上面的例子中,我想要一个b的输出,因为中位数是3。我试着用下面的代码使用NumPy,但无济于事:
import numpy as np
list = [('a',1), ('b',3), ('c',5)]
np.median(list, key=lambda x:x[1])
你可以这样计算中位数:
np.median(dict(list).values())
# in Python 2.7; in Python 3.x it would be `np.median(list(dict(list_of_tuples).values()))`
首先将列表转换为字典,然后计算其值的中位数。
当您想要获得实际的键时,您可以这样做:
dl = dict(list) #{'a': 1, 'b': 3, 'c': 5}
dl.keys()[dl.values().index(np.median(dl.values()))]
将打印'b'
。假设中位数在列表中,否则将抛出ValueError
。因此,您可以使用这样的try/except
,使用@Anand S Kumar的答案中的示例:
import numpy as np
l = [('a',1), ('b',3), ('c',5), ('d',22),('e',11),('f',3)]
# l = [('a',1), ('b',3), ('c',5)]
dl = dict(l)
try:
print(dl.keys()[dl.values().index(np.median(dl.values()))])
except ValueError:
print('The median is not in this list. Its value is ',np.median(dl.values()))
print('The closest key is ', dl.keys()[min(dl.values(), key=lambda x:abs(x-np.median(dl.values())))])
对于第一个列表,您将得到:
中位数不在此列表中。其值为4.0
最近的键是f
对于你的例子,它只是打印:
b
np.median
不接受任何称为key
的参数。相反,您可以使用列表推导式,只从内部列表中取出第二个元素。例子——
In [3]: l = [('a',1), ('b',3), ('c',5)]
In [4]: np.median([x[1] for x in l])
Out[4]: 3.0
In [5]: l = [('a',1), ('b',3), ('c',5), ('d',22),('e',11),('f',3)]
In [6]: np.median([x[1] for x in l])
Out[6]: 4.0
另外,如果不是用于示例目的,不要使用list
作为变量名,它会遮蔽内置函数list
。
np.median
不接受某种'key'参数,并且不返回它找到的索引。此外,当有偶数个项目(沿轴)时,它返回2个中心项目的平均值。
但是median
用来查找中心项的np.partition
确实接受结构化数组字段名。因此,如果将元组列表转换为结构化数组,则可以轻松地选择中间项。
列表:
In [1001]: ll
Out[1001]: [('a', 1), ('b', 3), ('c', 5)]
作为结构化数组:
In [1002]: la1 = np.array(ll,dtype='a1,i')
In [1003]: la1
Out[1003]:
array([(b'a', 1), (b'b', 3), (b'c', 5)],
dtype=[('f0', 'S1'), ('f1', '<i4')])
我们可以得到中间的项(1
for size 3):
In [1115]: np.partition(la1, (1), order='f1')[[1]]
Out[1115]:
array([(b'b', 3)],
dtype=[('f0', 'S1'), ('f1', '<i4')])
并允许偶数项(代码取自np.median
):
def mymedian1(arr, field):
# return the middle items of arr, selected by field
sz = arr.shape[0] # 1d for now
if sz % 2 == 0:
ind = ((sz // 2)-1, sz // 2)
else:
ind = ((sz - 1) // 2,)
return np.partition(arr, ind, order=field)[list(ind)]
为3项数组:
In [1123]: mymedian1(la1,'f1')
Out[1123]:
array([(b'b', 3)],
dtype=[('f0', 'S1'), ('f1', '<i4')])
表示包含6个元素的数组:
In [1124]: la2
Out[1124]:
array([(b'a', 1), (b'b', 3), (b'c', 5), (b'd', 22), (b'e', 11), (b'f', 3)],
dtype=[('f0', 'S1'), ('f1', '<i4')])
In [1125]: mymedian1(la2,'f1')
Out[1125]:
array([(b'f', 3), (b'c', 5)],
dtype=[('f0', 'S1'), ('f1', '<i4')])
查看我使用np.argpartition
的早期版本的编辑历史。
它甚至适用于第一个字段(字符):
In [1132]: mymedian1(la2,'f0')
Out[1132]:
array([(b'c', 5), (b'd', 22)],
dtype=[('f0', 'S1'), ('f1', '<i4')])