Python 根据其标签的子集
假设我有两个列表:Python 根据其标签的子集,python,numpy,zip,list-comprehension,Python,Numpy,Zip,List Comprehension,假设我有两个列表:字母=[a,b,c,d,e,f,g,h,I]和数字=[0,1,1,2,1,1,0,2,1,0]。我希望最终结果是output=[[a,f,I],[b,c,e,I],[d,g,h] 这里的0、1和2是不同的类。例如,a来自class0,而b和c来自class1。我只需要根据字母的类别将其放入子列表中 我想我可以在这里给你zip()和一个列表,但我不知道怎么做。如何使用numpy实现这一点?您可以使用zip()和临时字典: letters = ['a', 'b', 'c', 'd'
字母=[a,b,c,d,e,f,g,h,I]
和数字=[0,1,1,2,1,1,0,2,1,0]
。我希望最终结果是output=[[a,f,I],[b,c,e,I],[d,g,h]
这里的
0
、1
和2
是不同的类。例如,a
来自class0
,而b
和c
来自class1
。我只需要根据字母的类别将其放入子列表中
我想我可以在这里给你zip()
和一个列表,但我不知道怎么做。如何使用numpy实现这一点?您可以使用zip()
和临时字典:
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
digits = [0, 1, 1, 2, 1, 0, 2, 2, 1, 0]
tmp = {}
for d, l in zip(digits, letters):
tmp.setdefault(d, []).append(l)
out = []
for k in sorted(tmp):
out.append(tmp[k])
print(out)
印刷品:
[['a', 'f'], ['b', 'c', 'e', 'i'], ['d', 'g', 'h']]
或者:另一个版本(使用
itertools.groupby
):
答案的另一个变体(这里有
groupby
和itemgetter
):
从itertools导入groupby
从运算符导入itemgetter
字母=['a','b','c','d','e','f','g','h','i']
数字=[0,1,1,2,1,0,2,2,1,0]
组合字母数字=排序(zip(字母,数字),键=itemgetter(1))
字母\组=分组依据(组合字母\数字,itemgetter(1))
out=[[group_数据中的项的项[0]对于字母组中的(键,group_数据)]
打印(输出)
更加简洁,没有带熊猫的循环
import pandas as pd
s = pd.Series(
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
index=[0, 1, 1, 2, 1, 0, 2, 2, 1],
name='letters'
)
[*s.groupby(level=0).agg(list)]
[['a', 'f'], ['b', 'c', 'e', 'i'], ['d', 'g', 'h']]
numpy
解决方案也是可能的:
digits = np.array([0, 1, 1, 2, 1, 0, 2, 2, 0])
letters = np.array(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
argidx = np.argsort(digits)
digits, letters = digits[argidx], letters[argidx]
markers = np.diff(digits, prepend=digits[0])
marker_idx, = np.nonzero(markers)
np.split(letters, marker_idx)
输出:
[array(['a', 'f', 'i'], dtype='<U1'), array(['b', 'c', 'e'], dtype='<U1'), array(['d', 'g', 'h'], dtype='<U1')]
[array(['a',f',i',dtype=',因为您标记了numpy(我个人更喜欢pandas groupby,因为它是干净的,用于此目的):
你能解释一下你是如何得到所需的输出的吗?0
,1
和2
只是不同的类。例如,a
来自类0
,而b
和c
来自类1
。我只需要根据它们的类将字母放入子列表中。我不知道由于类的数量可能会有所不同,您可能需要使用tmp.values()
此处取而代之,而不是在diff
中预先添加以重新分配内存,您可能希望在marker\u idx
中添加1。此外,flatnonzero
比此处的非零
更简单。+1是正确的numpy解决方案。忽略nitpicking@Mad我见过的物理学家不受欢迎,但并没有I don’我不认为它在内存方面效率低下。这些都是很好的提示。prepend
调用np。在纯python代码部分连接。这很难看。
[array(['a', 'f', 'i'], dtype='<U1'), array(['b', 'c', 'e'], dtype='<U1'), array(['d', 'g', 'h'], dtype='<U1')]
d,l = list(zip(*(sorted(zip(digits,letters)))))
d = np.array(d)
idx = np.flatnonzero(np.r_[True, d[:-1] != d[1:], True])
output = [list(l[i:j]) for i,j in zip(idx[:-1],idx[1:])]
#[['a', 'f'], ['b', 'c', 'e', 'i'], ['d', 'g', 'h']]