Перемішати два списки одночасно з однаковим порядком


89

Я використовую корпус nltkбібліотеки, movie_reviewsякий містить велику кількість документів. Моє завдання - отримати прогнозовану ефективність цих оглядів з попередньою обробкою даних та без попередньої обробки. Але є проблема, у списках, documentsі у documents2мене однакові документи, і мені потрібно перемішати їх, щоб зберегти однаковий порядок в обох списках. Я не можу перетасувати їх окремо, оскільки кожного разу, коли я перебираю список, я отримую інші результати. Ось чому мені потрібно перемішати відразу з тим самим порядком, тому що мені потрібно порівняти їх в кінці (це залежить від порядку). Я використовую 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

Відповіді:


219

Ви можете зробити це як:

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]

Звичайно, це був приклад із простішими списками, але адаптація буде однаковою для вашого випадку.

Сподіваюся, це допоможе. Щасти.


Дякую, це саме те, що мені потрібно.
Ярослав Клімчик

4
(запитання noob) - що означає *?
ᔕᖺᘎᕊ

2
@ ᔕᖺᘎᕊ, Це означає розпакувати значення c, тому його називають як zip(1,2,3)замістьzip([1,2,3])
sshashank124

2
Я використовував це рішення раніше і, aі це bбули списки в кінці. З Python 3.6.8, наприкінці того ж прикладу, я отримую aі bяк кортежі.
vinzee

1
... Кортежі ... так просто a = list (a) і b = list (b)
RichardBJ

37

Я отримую простий спосіб зробити це

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. Ви щойно врятували мій день!
finngu

10
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

Перемішати довільну кількість списків одночасно.

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.

PS 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

Простий і швидкий спосіб зробити це - використовувати 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]

Це також працює, коли через проблеми з пам’яттю ви не можете одночасно працювати з обома списками.


2
чи не повинно бути випадковим чином. перетасувати (а)?
Хан

-2

Ви можете використати другий аргумент функції перетасовки, щоб визначити порядок перетасовки.

Зокрема, ви можете передати другому аргументу функції перетасування функцію нульового аргументу, яка повертає значення в [0, 1). Повернене значення цієї функції фіксує порядок перетасовки. (За замовчуванням, тобто якщо ви не передаєте жодну функцію як другий аргумент, вона використовує функцію random.random(). Ви можете побачити це в рядку 277 тут .)

Цей приклад ілюструє те, що я описав:

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що завжди повертає те ж значення може мати непередбачувані наслідки для виведення.
Blckknght

Ти правий. Це буде упередженим перемішуванням, залежно від значення r. Це може бути практично добре для багатьох випадків, але не завжди.
Кундан Кумар,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.