随机排列 DataFrame 行
Shuffle DataFrame rows
我有以下数据框:
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
...
我怎样才能做到这一点?
您可以通过使用已打乱的索引进行索引来打乱数据框的行。为此,您可以使用 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 开始,就像你的例子一样,你可以简单地重置索引:df_shuffled.reset_index(drop=True)
使用 Pandas 执行此操作的惯用方法是使用数据框的 .sample
方法对所有行进行无替换采样:
df.sample(frac=1)
frac
关键字参数指定随机样本中 return 行的分数,因此 frac=1
表示 return 所有行(以随机顺序)。
注:
如果你想洗牌你的数据帧 in-place 并重置索引,你可以这样做
df = df.sample(frac=1).reset_index(drop=True)
此处,指定 drop=True
可防止 .reset_index
创建包含旧索引条目的列。
Follow-up注:虽然上面的操作看起来可能不像是in-place,python/pandas 足够聪明,不会为洗牌后的对象再做一次 malloc。也就是说,即使 reference 对象已更改(我的意思是 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)
你可以简单地使用 sklearn
来完成这个
from sklearn.utils import shuffle
df = shuffle(df)
TL;DR: np.random.shuffle(ndarray)
可以胜任。
所以,在你的情况下
np.random.shuffle(DataFrame.values)
DataFrame
,在幕后,使用 NumPy ndarray 作为数据持有者。 (您可以从DataFrame source code查看)
因此,如果您使用 np.random.shuffle()
,它会沿 multi-dimensional 数组的第一个轴打乱数组。但是 DataFrame
的索引保持不变。
不过,有几点需要考虑。
- 函数returnsnone。如果您想保留原始对象的副本,则必须在传递给函数之前这样做。
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 秒
数据帧
df = sklearn.utils.shuffle(df)
0.3183923360193148 秒。 快 3 倍
np.random.shuffle(df.values)
0.9357550159329548 秒
Conclusion: If it is okay to axis info(index, column) to be shuffled along with ndarray, use sklearn.utils.shuffle()
. Otherwise, use 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)
通过在本例中采用样本数组 index 随机化 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
将你的数据框插入到上面代码中我的位置。
这是另一种方法:
df_shuffled = df.reindex(np.random.permutation(df.index))
(我没有足够的声誉在顶部评论此 post,所以我希望其他人可以为我做这件事。) 有一个第一种方法引起关注:
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
这意味着该方法 不是 返回相同的对象,如上一条评论中所建议的那样。所以这个方法确实做了一个洗牌 copy.
这是另一种方式:
df['rnd'] = np.random.rand(len(df))
df = df.sort_values(by='rnd', inplace=True).drop('rnd', axis=1)
还有什么有用的,如果您将它用于 Machine_learning 并希望始终分离相同的数据,您可以使用:
df.sample(n=len(df), random_state=42)
这确保您的随机选择始终可复制
以下可能是其中一种方法:
dataframe = dataframe.sample(frac=1, random_state=42).reset_index(drop=True)
哪里
frac=1表示一个数据框的所有行
random_state=42表示每次执行都保持相同的顺序
reset_index(drop=True) 表示重新初始化随机数据帧的索引
通过传递 frac
参数,使用 sample() 随机播放 DataFrame。
将打乱后的 DataFrame 保存到新变量中。
new_variable = DataFrame.sample(frac=1)
我有以下数据框:
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
...
我怎样才能做到这一点?
您可以通过使用已打乱的索引进行索引来打乱数据框的行。为此,您可以使用 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 开始,就像你的例子一样,你可以简单地重置索引:df_shuffled.reset_index(drop=True)
使用 Pandas 执行此操作的惯用方法是使用数据框的 .sample
方法对所有行进行无替换采样:
df.sample(frac=1)
frac
关键字参数指定随机样本中 return 行的分数,因此 frac=1
表示 return 所有行(以随机顺序)。
注: 如果你想洗牌你的数据帧 in-place 并重置索引,你可以这样做
df = df.sample(frac=1).reset_index(drop=True)
此处,指定 drop=True
可防止 .reset_index
创建包含旧索引条目的列。
Follow-up注:虽然上面的操作看起来可能不像是in-place,python/pandas 足够聪明,不会为洗牌后的对象再做一次 malloc。也就是说,即使 reference 对象已更改(我的意思是 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)
你可以简单地使用 sklearn
来完成这个
from sklearn.utils import shuffle
df = shuffle(df)
TL;DR: np.random.shuffle(ndarray)
可以胜任。
所以,在你的情况下
np.random.shuffle(DataFrame.values)
DataFrame
,在幕后,使用 NumPy ndarray 作为数据持有者。 (您可以从DataFrame source code查看)
因此,如果您使用 np.random.shuffle()
,它会沿 multi-dimensional 数组的第一个轴打乱数组。但是 DataFrame
的索引保持不变。
不过,有几点需要考虑。
- 函数returnsnone。如果您想保留原始对象的副本,则必须在传递给函数之前这样做。
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 秒
数据帧
df = sklearn.utils.shuffle(df)
0.3183923360193148 秒。 快 3 倍
np.random.shuffle(df.values)
0.9357550159329548 秒
Conclusion: If it is okay to axis info(index, column) to be shuffled along with ndarray, use
sklearn.utils.shuffle()
. Otherwise, usenp.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)
通过在本例中采用样本数组 index 随机化 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
将你的数据框插入到上面代码中我的位置。
这是另一种方法:
df_shuffled = df.reindex(np.random.permutation(df.index))
(我没有足够的声誉在顶部评论此 post,所以我希望其他人可以为我做这件事。) 有一个第一种方法引起关注:
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
这意味着该方法 不是 返回相同的对象,如上一条评论中所建议的那样。所以这个方法确实做了一个洗牌 copy.
这是另一种方式:
df['rnd'] = np.random.rand(len(df))
df = df.sort_values(by='rnd', inplace=True).drop('rnd', axis=1)
还有什么有用的,如果您将它用于 Machine_learning 并希望始终分离相同的数据,您可以使用:
df.sample(n=len(df), random_state=42)
这确保您的随机选择始终可复制
以下可能是其中一种方法:
dataframe = dataframe.sample(frac=1, random_state=42).reset_index(drop=True)
哪里
frac=1表示一个数据框的所有行
random_state=42表示每次执行都保持相同的顺序
reset_index(drop=True) 表示重新初始化随机数据帧的索引
通过传递 frac
参数,使用 sample() 随机播放 DataFrame。
将打乱后的 DataFrame 保存到新变量中。
new_variable = DataFrame.sample(frac=1)