DataFrame satırlarını karıştır

Aşağıdaki DataFrame'e sahibim:

    Col1  Col2  Col3  Type
0      1     2     3     1
1      4     5     6     1
...
20     7     8     9     2
21    10    11    12     2
...
45    13    14    15     3
46    16    17    18     3
...

DataFrame, bir csv dosyasından okunur. Tip 1 olan tüm satırlar üstte, ardından Tip 2 ve ardından Tip 3 vb. İçeren satırlar bulunur.

DataFrame'in satırlarını karıştırmak istiyorum, böylece tüm Type ları karışır. Olası bir sonuç olabilir:

    Col1  Col2  Col3  Type
0      7     8     9     2
1     13    14    15     3
...
20     1     2     3     1
21    10    11    12     2
...
45     4     5     6     1
46    16    17    18     3
...

Sonuçtan görülebileceği gibi, sıraların sırası karıştırılır, ancak sütunlar aynı kalır. Bunu açıkça açıklıyor muyum bilmiyorum. Yapmazsam bana haber ver.

Bunu nasıl başarabilirim?

161

7 cevap

Bunu pandalarla yapmanın daha deyimatik yolu, veri çerçevenizin .sample yöntemini kullanmak, yani.

df.sample(frac=1)

frac anahtar sözcük argümanı, rastgele örnekte döndürülecek satırların oranını belirtir, bu nedenle frac = 1 tüm satırları döndürür (rastgele sırayla).

Note: If you wish to shuffle your dataframe in-place and reset the index, you could do e.g.

df = df.sample(frac=1).reset_index(drop=True)

Burada, drop = True belirtilmesi, .reset_index öğesinin eski dizin girişlerini içeren bir sütun oluşturmasını önler.

329
katma
reset_index karıştırmanın çalışmasını sağlar !!!
katma yazar 0709_, kaynak
Yeniden. notunuz , sample() yönteminizde inplace parametresi bulunmuyor, bu nedenle (şu anda) yaptığınız şeyi yapmanın mümkün olmadığı anlaşılıyor. yeni bir nesne oluşturmadan önerildi.
katma yazar m-dz, kaynak
Yukarıdan alıntı "Not: Dataframe'inizi yerinde karıştırmak istiyorsanız [...]".
katma yazar m-dz, kaynak
Elbette, lütfen df.sample (frac = 1) .reset_index (drop = True) df yerinde nasıl karıştırdığını açıklar mısınız?
katma yazar m-dz, kaynak
Evet, bu tam olarak ilk yorumumda göstermek istediğim şeydi, gerekli hafızayı iki kez atamanız gerekiyor, bu da yerine oturmaktan oldukça uzak.
katma yazar m-dz, kaynak
Bildiğim kadarıyla, yeni bir nesne döndüren sample() 'u kullandıktan sonra değil. print (hex (id (df))) ve print (hex (id (df.sample (frac = 1) .reset_index (drop = True)))) 'i deneyin . Fakat yanılıyor olabilirim, temel olarak burada bir onay veya olumsuzlama istemek istedim.
katma yazar m-dz, kaynak
Sonuçları varsa ping burada seviniriz.
katma yazar m-dz, kaynak
@ m-dz Gerçekten önerdiklerimi okudun mu?
katma yazar Kris, kaynak
@ m-dz Evet ... bu cümlenin kalanını okudunuz mu?
katma yazar Kris, kaynak
Öyle değil. Bu satır sadece df nesnesini yeniden atar ve böylece nesneyi etkin şekilde değiştirir. Geçici bir çözüm olarak görün.
katma yazar Kris, kaynak
@ m-dz Hatalıysam beni düzelt, ancak .copy() yapmazsan, hala aynı temel nesneye atıfta bulunuyorsun.
katma yazar Kris, kaynak
Tamam, zamanım olduğunda bunu bir hafıza profilleyicisiyle çalıştıracağım. Teşekkürler
katma yazar Kris, kaynak
hayır, DataFrame'i kopyalamaz, yalnızca şu satıra bakın: github.com/pandas-dev/pandas/blob/v0.23.0/pandas/core/…
katma yazar ngọcminh.oss, kaynak

Bunun için sklearn'ü kullanabilirsiniz.

from sklearn.utils import shuffle
df = shuffle(df)
97
katma

Bir veri çerçevesinin satırlarını, karıştırılmış bir dizinle indeksleyerek karışık yapabilirsiniz. Bunun için, örneğin np.random.permutation 'ı kullanabilirsiniz (ancak np.random.choice da bir olasılıktır):

In [12]: df = pd.read_csv(StringIO(s), sep="\s+")

In [13]: df
Out[13]: 
    Col1  Col2  Col3  Type
0      1     2     3     1
1      4     5     6     1
20     7     8     9     2
21    10    11    12     2
45    13    14    15     3
46    16    17    18     3

In [14]: df.iloc[np.random.permutation(len(df))]
Out[14]: 
    Col1  Col2  Col3  Type
46    16    17    18     3
45    13    14    15     3
20     7     8     9     2
0      1     2     3     1
1      4     5     6     1
21    10    11    12     2

If you want to keep the index numbered from 1, 2, .., n as in your example, you can simply reset the index: df_shuffled.reset_index(drop=True)

44
katma

TL;DR: np.random.shuffle(ndarray) can do the job.
So, in your case

np.random.shuffle(Veri çerçevesi.values)

Anlayışıma dayanarak, Veri çerçevesi, başlık altında, veri sahibi olarak NumPy ndarray kullanıyor. Veri çerçevesi kaynak kodunu kontrol edebilirsiniz. . Öyleyse np.random.shuffle ( ) , diziyi çok boyutlu bir dizinin ilk ekseni boyunca karıştırır. Fakat sütunlar aynı kalır.

Bazı sınırlamalar aşağıdaki gibidir.

  • function returns none. In case you want to keep a copy of the original object, you have to do so before you pass to the function.
  • sklearn.utils.shuffle() user tj89 suggested, can designate random_state along with another option to control output. You may want that for dev purpose.

Kıyaslama sonucu

sklearn.utils.shuffle() arasında ve np.random.shuffle() .

ndarray

nd = sklearn.utils.shuffle(nd)

0.10793248389381915 sec. 8x faster

np.random.shuffle(nd)

0.8897626010002568 sn

Veri çerçevesi

df = sklearn.utils.shuffle(df)

0.3183923360193148 sec. 3x faster

np.random.shuffle(df.values)', setup=setup, number=1000)

0.9357550159329548 sn

Sonuç: sklearn.utils.shuffle ( ) , mümkünse.

kullanılan kod

setup = '''
import numpy as np
import pandas as pd
from sklearn.utils import shuffle
nd = np.random.random((1000, 100))
df = pd.Veri çerçevesi(nd)
'''

timeit.timeit('nd = sklearn.utils.shuffle(nd)', setup=setup, number=1000)
timeit.timeit('np.random.shuffle(nd)', setup=setup, number=1000)
timeit.timeit('df = sklearn.utils.shuffle(df)', setup=setup, number=1000)
timeit.timeit('np.random.shuffle(df.values)', setup=setup, number=1000)

13
katma

(I don't have enough reputation to comment this on the top post, so I hope someone else can do that for me.) There was a concern raised that the first method:

df.sample(frac=1)

derin bir kopyasını yaptı veya sadece veri çerçevesini değiştirdi. Aşağıdaki kodu koştum:

print(hex(id(df)))
print(hex(id(df.sample(frac=1))))
print(hex(id(df.sample(frac=1).reset_index(drop=True))))

ve sonuçlarım:

0x1f8a784d400
0x1f8b9d65e10
0x1f8b9d65b70

bu, yöntemin son açıklamada önerildiği gibi aynı nesneyi döndürmediğini değil olduğu anlamına gelir. Dolayısıyla bu yöntem gerçekten karıştırılmış bir kopya yapar.

2
katma

AFAIK en basit çözüm:

df_shuffled = df.reindex(np.random.permutation(df.index))
1
katma

Bu durumda index 'de örnek bir dizi alarak pandaların veri çerçevesini karıştırın ve sırasını randomize edin, ardından diziyi bir veri çerçevesi dizini olarak ayarlayın. Şimdi veri çerçevesini dizine göre sıralayın. İşte karıştırılmış dataframe'inize gider

import random
df = pd.DataFrame({"a":[1,2,3,4],"b":[5,6,7,8]})
index = [i for i in range(df.shape[0])]
random.shuffle(index)
df.set_index([index]).sort_index()

çıkışı

    a   b
0   2   6
1   1   5
2   3   7
3   4   8

Veri çerçevesini yukarıdaki kodda benim yerime yerleştirin.

0
katma