问题:随机播放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
...
从csv文件读取DataFrame。所有具有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
...
我该如何实现?
回答 0
使用Pandas的惯用方式是使用.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)
回答 1
您可以为此简单地使用sklearn
from sklearn.utils import shuffle
df = shuffle(df)
回答 2
您可以通过使用改组后的索引建立索引来改组数据帧的行。为此,您可以使用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)
回答 3
TL; DR:np.random.shuffle(ndarray)
可以胜任。
所以,在你的情况下
np.random.shuffle(DataFrame.values)
DataFrame
在后台,使用NumPy ndarray作为数据持有者。(您可以从DataFrame源代码检查)
因此,如果使用DataFrame
遗体的索引仍然没有改组。
虽然,有一些要考虑的问题。
- 函数不返回任何内容。如果要保留原始对象的副本,则必须这样做,然后再传递给该函数。
,如用户tj89所建议的那样,可以指定 random_state
其他选项来控制输出。您可能需要出于开发目的。是比较快的。但洗牌的轴信息(索引,列) 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秒
结论:如果可以将轴信息(索引,列)与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)
回答 4
(我没有足够的声誉在最高职位上对此发表评论,所以我希望其他人可以为我这样做。)第一种方法引起了人们的关注:
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
这意味着该方法未返回上一个注释中建议的相同对象。因此,此方法的确可以制作随机的副本。
回答 5
还有用的是,如果将其用于Machine_learning并且希望始终分离相同的数据,则可以使用:
df.sample(n=len(df), random_state=42)
这样可以确保您的随机选择始终可复制
回答 6
AFAIK最简单的解决方案是:
df_shuffled = df.reindex(np.random.permutation(df.index))
回答 7
通过取样阵列中的这种情况下,洗牌大熊猫数据帧索引和随机那么它的顺序来设置所述阵列的数据帧的索引。现在根据索引对数据帧进行排序。这是您经过改组的数据框
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
这是另一种方式:
df['rnd'] = np.random.rand(len(df))
df = df.sort_values(by='rnd', inplace=True).drop('rnd', axis=1)