Перемешать строки DataFrame
У меня есть следующий DataFrame:
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 считывается из CSV файла. Все строки с Type
1 находятся сверху, за ними следуют строки с Type
2, за которыми следуют строки с Type
3 и т.д.
Я хотел бы, чтобы перетасовать порядок DataFrame строк, так что все Type
смешиваются. Возможный результат может быть:
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
...
Как мне этого добиться?
Ответы
Ответ 1
Идиоматический способ сделать это с пандами - это использовать метод .sample
вашего фрейма данных, т.е.
df.sample(frac=1)
Ключевой аргумент frac
определяет долю строк, возвращаемых в случайной выборке, поэтому frac=1
означает возвращение всех строк (в случайном порядке).
Примечание:
Если вы хотите переместить ваш фрейм данных на месте и сбросить индекс, вы можете сделать, например,
df = df.sample(frac=1).reset_index(drop=True)
Здесь указание drop=True
не позволяет .reset_index
создавать столбец, содержащий старые записи индекса.
Последующее замечание: Несмотря на то, что приведенная выше операция может выглядеть неэффективно, Python/pandas достаточно умен, чтобы не выполнять другой malloc для перемешанного объекта. То есть, даже если эталонный объект изменился (я имею в виду id(df_old)
не совпадает с id(df_new)
), базовый объект C остается тем же. Чтобы показать, что это действительно так, вы можете запустить простой профилировщик памяти:
$ python3 -m memory_profiler .\test.py
Filename: .\test.py
Line # Mem usage Increment Line Contents
================================================
5 68.5 MiB 68.5 MiB @profile
6 def shuffle():
7 847.8 MiB 779.3 MiB df = pd.DataFrame(np.random.randn(100, 1000000))
8 847.9 MiB 0.1 MiB df = df.sample(frac=1).reset_index(drop=True)
Ответ 2
Вы можете просто использовать sklearn для этого
from sklearn.utils import shuffle
df = shuffle(df)
Ответ 3
Вы можете перемешать строки фрейма данных путем индексирования с перетасованным индексом. Для этого вы можете использовать np.random.permutation
(но np.random.choice
также возможность):
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
Если вы хотите сохранить индекс с номерами 1, 2,.., n, как в вашем примере, вы можете просто reset индекс: df_shuffled.reset_index(drop=True)
Ответ 4
TL; DR: np.random.shuffle(ndarray)
может сделать эту работу.
Итак, в вашем случае
np.random.shuffle(DataFrame.values)
DataFrame
, под капотом, использует NumPy ndarray в качестве владельца данных. (Вы можете проверить из исходного кода DataFrame)
Поэтому, если вы используете np.random.shuffle()
, он будет перетасовывать массив вдоль первой оси многомерного массива. Но индекс DataFrame
остается не перетасованным.
Хотя есть некоторые моменты, которые следует учитывать.
- функция не возвращает ничего. Если вы хотите сохранить копию исходного объекта, вы должны сделать это, прежде чем перейти к функции.
-
sklearn.utils.shuffle()
, как предложил пользователь tj89, может назначать random_state
вместе с другой опцией для управления выводом. Вы можете хотеть это для цели разработки. -
sklearn.utils.shuffle()
быстрее. Но будет перемешивать информацию об оси (индекс, столбец) DataFrame
вместе с ndarray
он содержит.
Результат теста
между sklearn.utils.shuffle()
и np.random.shuffle()
.
ndarray
nd = sklearn.utils.shuffle(nd)
0,10793248389381915 сек. В 8 раз быстрее
np.random.shuffle(nd)
0,8897626010002568 с
DataFrame
df = sklearn.utils.shuffle(df)
0,3183923360193148 сек. В 3 раза быстрее
np.random.shuffle(df.values)
0,9357550159329548 сек
Вывод: если информация оси (индекс, столбец) может быть перетасована вместе с ndarray, используйте sklearn.utils.shuffle()
. В противном случае используйте np.random.shuffle()
используемый код
import timeit
setup = '''
import numpy as np
import pandas as pd
import sklearn
nd = np.random.random((1000, 100))
df = pd.DataFrame(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)
python benchmarking
Ответ 5
(У меня недостаточно репутации, чтобы комментировать это в верхнем посте, поэтому я надеюсь, что кто-то другой может сделать это для меня.) Была высказана обеспокоенность, что первый метод:
df.sample(frac=1)
сделал глубокую копию или просто изменил фрейм данных. Я запустил следующий код:
print(hex(id(df)))
print(hex(id(df.sample(frac=1))))
print(hex(id(df.sample(frac=1).reset_index(drop=True))))
и мои результаты были:
0x1f8a784d400
0x1f8b9d65e10
0x1f8b9d65b70
Это означает, что метод не возвращает тот же объект, как было предложено в последнем комментарии. Таким образом, этот метод действительно делает случайную копию.
Ответ 6
AFAIK самое простое решение:
df_shuffled = df.reindex(np.random.permutation(df.index))
Ответ 7
перетасуйте кадр данных pandas, взяв образец массива в этом случае индекса и рандомизируйте его порядок, а затем установите массив в качестве индекса кадра данных. Теперь отсортируйте фрейм данных по индексу. Вот твой перетасованный кадр данных
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()
выход
a b
0 2 6
1 1 5
2 3 7
3 4 8
Вставьте свой фрейм данных вместо моего в приведенном выше коде.
Ответ 8
Простейший способ сделать это приведенный ниже код. (Python)
from sklearn.utils import shuffle
dataFrame = shuffle(dataFrame)
Это будет перетаскивать все столбцы, и вы будете иметь хорошее сочетание всех, так что все Type
смешаны
Ответ 9
Что также полезно, если вы используете его для Machine_learning и хотите всегда разделять одни и те же данные, вы можете использовать:
df.sample(n=len(df), random_state=42)
это гарантирует, что ваш случайный выбор всегда будет воспроизводимым
Ответ 10
Вот еще один способ:
df['rnd'] = np.random.rand(len(df)) df = df.sort_values(by='rnd', inplace=True).drop('rnd', axis=1)