【问题标题】:Shuffle two list at once with same order以相同的顺序一次洗牌两个列表
【发布时间】:2021-06-22 06:20:01
【问题描述】:

我正在使用 nltk 库的 movie_reviews 语料库,其中包含大量文档。我的任务是通过数据预处理而不是预处理来预测这些评论的性能。但是有一个问题,在documentsdocuments2 列表中,我有相同的文件,我需要对它们进行洗牌,以便在两个列表中保持相同的顺序。我不能单独洗牌,因为每次洗牌时,我都会得到其他结果。这就是为什么我需要用相同的顺序一次洗牌,因为我需要最后比较它们(这取决于顺序)。我正在使用 python 2.7

示例(实际上是标记化的字符串,但不是相对的):

documents = [(['plot : two teen couples go to a church party , '], 'neg'),
             (['drink and then drive . '], 'pos'),
             (['they get into an accident . '], 'neg'),
             (['one of the guys dies'], 'neg')]

documents2 = [(['plot two teen couples church party'], 'neg'),
              (['drink then drive . '], 'pos'),
              (['they get accident . '], 'neg'),
              (['one guys dies'], 'neg')]

我需要在随机播放两个列表后得到这个结果:

documents = [(['one of the guys dies'], 'neg'),
             (['they get into an accident . '], 'neg'),
             (['drink and then drive . '], 'pos'),
             (['plot : two teen couples go to a church party , '], 'neg')]

documents2 = [(['one guys dies'], 'neg'),
              (['they get accident . '], 'neg'),
              (['drink then drive . '], 'pos'),
              (['plot two teen couples church party'], 'neg')]

我有这个代码:

def cleanDoc(doc):
    stopset = set(stopwords.words('english'))
    stemmer = nltk.PorterStemmer()
    clean = [token.lower() for token in doc if token.lower() not in stopset and len(token) > 2]
    final = [stemmer.stem(word) for word in clean]
    return final

documents = [(list(movie_reviews.words(fileid)), category)
             for category in movie_reviews.categories()
             for fileid in movie_reviews.fileids(category)]

documents2 = [(list(cleanDoc(movie_reviews.words(fileid))), category)
             for category in movie_reviews.categories()
             for fileid in movie_reviews.fileids(category)]

random.shuffle( and here shuffle documents and documents2 with same order) # or somehow

【问题讨论】:

标签: python list sorting shuffle


【解决方案1】:

你可以这样做:

import random

a = ['a', 'b', 'c']
b = [1, 2, 3]

c = list(zip(a, b))

random.shuffle(c)

a, b = zip(*c)

print a
print b

[OUTPUT]
['a', 'c', 'b']
[1, 3, 2]

当然,这是一个更简单的列表示例,但适应您的情况是一样的。

希望对您有所帮助。祝你好运。

【讨论】:

  • 谢谢,这正是我需要的。
  • (菜鸟问题)- * 是什么意思?
  • @ᔕᖺᘎᕊ,就是解压c的值,所以叫zip(1,2,3)而不是zip([1,2,3])
  • 我之前使用过这个解决方案,ab 是最后的列表。使用 Python 3.6.8,在同一示例的末尾,我得到 ab 作为元组。
  • ...元组...所以只有 a=list(a) 和 b=list(b)
【解决方案2】:

您可以使用 shuffle 函数的第二个参数来固定 shuffle 的顺序。

具体来说,您可以将 shuffle 函数的第二个参数传递给零参数函数,该函数返回 [0, 1) 中的值。这个函数的返回值固定了洗牌的顺序。 (默认情况下,即如果您不传递任何函数作为第二个参数,则它使用函数random.random()。您可以在第 277 行看到它here。)

这个例子说明了我所描述的:

import random

a = ['a', 'b', 'c', 'd', 'e']
b = [1, 2, 3, 4, 5]

r = random.random()            # randomly generating a real in [0,1)
random.shuffle(a, lambda : r)  # lambda : r is an unary function which returns r
random.shuffle(b, lambda : r)  # using the same function as used in prev line so that shuffling order is same

print a
print b

输出:

['e', 'c', 'd', 'a', 'b']
[5, 3, 4, 1, 2]

【讨论】:

  • random.shuffle 函数多次调用random 函数,因此使用始终返回相同值的lambda 可能会对输出顺序产生意想不到的影响。
  • 你是对的。这将是一个有偏差的洗牌,取决于 r 的值。在许多情况下它可能实际上很好,但并非总是如此。
【解决方案3】:

同时打乱任意数量的列表。

from random import shuffle

def shuffle_list(*ls):
  l =list(zip(*ls))

  shuffle(l)
  return zip(*l)

a = [0,1,2,3,4]
b = [5,6,7,8,9]

a1,b1 = shuffle_list(a,b)
print(a1,b1)

a = [0,1,2,3,4]
b = [5,6,7,8,9]
c = [10,11,12,13,14]
a1,b1,c1 = shuffle_list(a,b,c)
print(a1,b1,c1)

输出:

$ (0, 2, 4, 3, 1) (5, 7, 9, 8, 6)
$ (4, 3, 0, 2, 1) (9, 8, 5, 7, 6) (14, 13, 10, 12, 11)

注意:
shuffle_list() 返回的对象是tuples

附: shuffle_list() 也可以应用于numpy.array()

a = np.array([1,2,3])
b = np.array([4,5,6])

a1,b1 = shuffle_list(a,b)
print(a1,b1)

输出:

$ (3, 1, 2) (6, 4, 5)

【讨论】:

    【解决方案4】:

    我有一个简单的方法来做到这一点

    import numpy as np
    a = np.array([0,1,2,3,4])
    b = np.array([5,6,7,8,9])
    
    indices = np.arange(a.shape[0])
    np.random.shuffle(indices)
    
    a = a[indices]
    b = b[indices]
    # a, array([3, 4, 1, 2, 0])
    # b, array([8, 9, 6, 7, 5])
    

    【讨论】:

    • 原帖是关于python中的普通列表,但我需要一个numpy数组的解决方案。你刚刚拯救了我的一天!
    • 看来np.random.permutation(a.shape[0])会更简单
    【解决方案5】:
    from sklearn.utils import shuffle
    
    a = ['a', 'b', 'c','d','e']
    b = [1, 2, 3, 4, 5]
    
    a_shuffled, b_shuffled = shuffle(np.array(a), np.array(b))
    print(a_shuffled, b_shuffled)
    
    #random output
    #['e' 'c' 'b' 'd' 'a'] [5 3 2 4 1]
    

    【讨论】:

      【解决方案6】:

      简单快捷的方法是使用 random.seed() 和 random.shuffle() 。它可以让您多次生成相同的随机顺序。 它看起来像这样:

      a = [1, 2, 3, 4, 5]
      b = [6, 7, 8, 9, 10]
      seed = random.random()
      random.seed(seed)
      a.shuffle()
      random.seed(seed)
      b.shuffle()
      print(a)
      print(b)
      
      >>[3, 1, 4, 2, 5]
      >>[8, 6, 9, 7, 10]
      

      这也适用于由于内存问题而无法同时处理两个列表的情况。

      【讨论】:

      • 不应该是 random.shuffle(a) 吗?
      • 我认为getstate/setstate 会比分配一个特定的种子更好。
      【解决方案7】:

      您可以将值的顺序存储在变量中,然后同时对数组进行排序:

      array1 = [1, 2, 3, 4, 5]
      array2 = ["one", "two", "three", "four", "five"]
      
      order = range(len(array1))
      random.shuffle(order)
      
      newarray1 = []
      newarray2 = []
      for x in range(len(order)):
          newarray1.append(array1[order[x]])
          newarray2.append(array2[order[x]])
      
      print newarray1, newarray2
      

      【讨论】:

        【解决方案8】:

        这也有效:

        import numpy as np
        
        a = ['a', 'b', 'c']
        b = [1, 2, 3]
        
        rng = np.random.default_rng()
        
        state = rng.bit_generator.state
        rng.shuffle(a)
        # use same seeds for a & b!
        rng.bit_generator.state = state # set state to same state as before
        rng.shuffle(b)
        
        print(a)
        print(b)
        

        输出:

        ['b', 'a', 'c']
        [2, 1, 3]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-11-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多