Mélangez deux listes à la fois avec le même ordre

89

J'utilise nltkle movie_reviewscorpus de la bibliothèque qui contient un grand nombre de documents. Ma tâche est d'obtenir des performances prédictives de ces revues avec un prétraitement des données et sans prétraitement. Mais il y a un problème, dans les listes documentset documents2j'ai les mêmes documents et j'ai besoin de les mélanger afin de garder le même ordre dans les deux listes. Je ne peux pas les mélanger séparément car chaque fois que je mélange la liste, j'obtiens d'autres résultats. C'est pourquoi je dois mélanger les fichiers à la fois avec le même ordre car je dois les comparer à la fin (cela dépend de l'ordre). J'utilise python 2.7

Exemple (en réel, les chaînes sont tokenisées, mais ce n'est pas relatif):

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')]

Et j'ai besoin d'obtenir ce résultat après avoir mélangé les deux listes:

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')]

J'ai ce code:

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
Jaroslav Klimčík
la source
1
Reproduction
Rick Smith

Réponses:

217

Vous pouvez le faire comme:

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]

Bien sûr, c'était un exemple avec des listes plus simples, mais l'adaptation sera la même pour votre cas.

J'espère que cela aide. Bonne chance.

sshashank124
la source
Merci, c'est exactement ce dont j'ai besoin.
Jaroslav Klimčík
4
(question noob) - que signifie le *?
ᔕᖺᘎᕊ
2
@ ᔕᖺᘎᕊ, cela signifie décompresser les valeurs de c donc il est appelé comme zip(1,2,3)au lieu dezip([1,2,3])
sshashank124
2
J'ai utilisé cette solution avant et aet bétaient des listes à la fin. Avec Python 3.6.8, à la fin du même exemple, j'obtiens aet bsous forme de tuples.
vinzee
1
... Tuples ... donc juste a = list (a) et b = list (b)
RichardBJ
37

J'ai un moyen facile de le faire

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])
hua wei
la source
Le message original concerne les listes normales en python, mais j'avais besoin d'une solution pour les tableaux numpy. Vous venez de sauver ma journée!
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]
YScharf
la source
6

Mélangez simultanément un nombre arbitraire de listes.

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)

Production:

$ (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)

Remarque: les
objets renvoyés par shuffle_list()sont tuples.

PS shuffle_list()peut également être appliqué ànumpy.array()

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

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

Production:

$ (3, 1, 2) (6, 4, 5)
Lion Lai
la source
4

Un moyen simple et rapide de le faire est d'utiliser random.seed () avec random.shuffle (). Il vous permet de générer le même ordre aléatoire plusieurs fois. Il ressemblera à ceci:

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]

Cela fonctionne également lorsque vous ne pouvez pas travailler avec les deux listes en même temps, en raison de problèmes de mémoire.

Boris
la source
2
ne devrait-il pas être aléatoire.shuffle (a)?
Khan le
-2

Vous pouvez utiliser le deuxième argument de la fonction de lecture aléatoire pour fixer l'ordre de lecture aléatoire.

Plus précisément, vous pouvez passer le deuxième argument de la fonction shuffle une fonction d'argument zéro qui renvoie une valeur dans [0, 1). La valeur de retour de cette fonction fixe l'ordre de lecture aléatoire. (Par défaut, c'est-à-dire si vous ne passez aucune fonction comme deuxième argument, il utilise la fonction random.random(). Vous pouvez le voir à la ligne 277 ici .)

Cet exemple illustre ce que j'ai décrit:

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

Production:

['e', 'c', 'd', 'a', 'b']
[5, 3, 4, 1, 2]
Kundan Kumar
la source
La random.shufflefonction appelle la randomfonction plus d'une fois, donc l'utilisation de a lambdaqui renvoie toujours la même valeur peut avoir des effets inattendus sur l'ordre de sortie.
Blckknght
Tu as raison. Ce sera un mélange biaisé, en fonction de la valeur de r. Cela peut être pratiquement bon dans de nombreux cas, mais pas toujours.
Kundan Kumar