【问题标题】:Shuffle array by group in python在python中按组随机播放数组
【发布时间】: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


    【解决方案1】:

    你可以这样做:

    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]
    

    【讨论】:

      【解决方案2】:

      假设您的组编号始终按升序排列,您可以利用 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]
      

      【讨论】:

        猜你喜欢
        • 2016-07-16
        • 1970-01-01
        • 1970-01-01
        • 2023-03-28
        • 2017-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多