【发布时间】:2021-05-31 22:33:26
【问题描述】:
假设我有两个数组:
values = [1,2,3,4,5,6,7,8,9]
groups = [0,0,0,1,1,2,2,3,4]
是否可以仅在组内随机播放“值”?例如。第 0 组 (1,2,3) 中的元素将只相互打乱,第 1 组 (4,5) 中的元素将相互打乱,依此类推。
我有巨大的 numpy 数组,有什么有效的方法吗?
【问题讨论】:
标签: python performance numpy random
假设我有两个数组:
values = [1,2,3,4,5,6,7,8,9]
groups = [0,0,0,1,1,2,2,3,4]
是否可以仅在组内随机播放“值”?例如。第 0 组 (1,2,3) 中的元素将只相互打乱,第 1 组 (4,5) 中的元素将相互打乱,依此类推。
我有巨大的 numpy 数组,有什么有效的方法吗?
【问题讨论】:
标签: python performance numpy random
你可以这样做:
import numpy as np
np.random.seed(133)
values = np.array([1,2,3,4,5,6,7,8,9])
groups = np.array([0,0,0,1,1,2,2,3,4])
for index in np.unique(groups):
mask = groups==index
values[mask] = np.random.permutation(values[mask])
print(values)
输出:
[3 1 2 5 4 6 7 8 9]
【讨论】:
假设您的组编号始终按升序排列,您可以利用 Python 的排序稳定这一事实将值/组作为一个整体进行混洗,然后仅按组对结果进行排序。将组编号和值组合成一个您打乱的元组列表。然后仅使用组作为排序键对该元组列表进行排序并仅提取值部分
values = [1,2,3,4,5,6,7,8,9]
groups = [0,0,0,1,1,2,2,3,4]
import random
shuffled = random.sample([*zip(groups,values)],len(values))
values = [v for g,v in sorted(shuffled,key=lambda gs:gs[0])]
print(values)
print(groups)
[3, 1, 2, 5, 4, 7, 6, 8, 9]
[0, 0, 0, 1, 1, 2, 2, 3, 4]
如果您的组标识符不是有序的(或不连续的),您将需要形成组(索引),将它们逐组打乱,并将打乱的值放置在与每个组对应的特定位置子集:
values = [1,2,3,4,5,6,7,8,9]
groups = [0,1,0,1,0,2,3,3,2]
import random
gIndex = dict() # grouping dictionary {groupId:[indexes]}
for i,g in enumerate(groups):
gIndex.setdefault(g,[]).append(i) # value indexes by group id
shuffled = [None]*len(groups) # resulting shuffled value list
for indexes in gIndex.values(): # shuffle indexes by group
for i,j in zip(indexes,random.sample(indexes,len(indexes))):
shuffled[i] = values[j] # map old positions to new position
print(values)
print(groups)
print(shuffled)
[1, 2, 3, 4, 5, 6, 7, 8, 9] # original order
[0, 1, 0, 1, 0, 2, 3, 3, 2] # group identifiers
[3, 4, 1, 2, 5, 9, 8, 7, 6] # shuffled order (within groups)
你也可以使用第一种排序技术来做 ti,但它不会像使用字典那样高效:
indexes = sorted((g,i) for i,g in enumerate(groups))
newIndexes = sorted(random.sample(indexes,len(indexes)),key=lambda gi:gi[0])
shuffled = [None]*len(values)
for (_,i),(_,j) in zip(indexes,newIndexes):
shuffled[i] = values[j]
【讨论】: