通过行或按列在pandas中随机播放数据帧的简单有效方法是什么?即如何编写一个函数shuffle(df, n, axis=0)
,它接受一个数据帧,一些shuffle n
和一个轴(axis=0
是行,axis=1
是列)并返回一个副本已经洗牌n
次的数据帧。
编辑:键是在不破坏数据框的行/列标签的情况下执行此操作。如果你只是拖拽那些丢失所有信息的df.index
。我希望生成的df
与原始a
相同,除了行的顺序或列的顺序不同。
Edit2 :我的问题不明确。当我说洗牌行时,我的意思是每行独立洗牌。因此,如果您有两列b
和a
,我希望每行都进行自动调整,以便您在b
和for 1...n:
for each col in df: shuffle column
return new_df
之间没有相同的关联。如果你只是重新整理每一行,你就会这样做。类似的东西:
def shuffle(df, n, axis=0):
shuffled_df = df.copy()
for k in range(n):
shuffled_df.apply(np.random.shuffle(shuffled_df.values),axis=axis)
return shuffled_df
df = pandas.DataFrame({'A':range(10), 'B':range(10)})
shuffle(df, 5)
但希望比天真循环更有效率。这对我不起作用:
{{1}}
答案 0 :(得分:192)
使用numpy的random.permuation
函数:
In [1]: df = pd.DataFrame({'A':range(10), 'B':range(10)})
In [2]: df
Out[2]:
A B
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
8 8 8
9 9 9
In [3]: df.reindex(np.random.permutation(df.index))
Out[3]:
A B
0 0 0
5 5 5
6 6 6
3 3 3
8 8 8
7 7 7
9 9 9
1 1 1
2 2 2
4 4 4
答案 1 :(得分:78)
采样随机化,因此只需对整个数据帧进行采样。
df.sample(frac=1)
答案 2 :(得分:30)
In [16]: def shuffle(df, n=1, axis=0):
...: df = df.copy()
...: for _ in range(n):
...: df.apply(np.random.shuffle, axis=axis)
...: return df
...:
In [17]: df = pd.DataFrame({'A':range(10), 'B':range(10)})
In [18]: shuffle(df)
In [19]: df
Out[19]:
A B
0 8 5
1 1 7
2 7 3
3 6 2
4 3 4
5 0 1
6 9 0
7 4 6
8 2 8
9 5 9
答案 3 :(得分:18)
您可以使用sklearn.utils.shuffle()
(requires sklearn 0.16.1或更高版本来支持Pandas数据框):
# Generate data
import pandas as pd
df = pd.DataFrame({'A':range(5), 'B':range(5)})
print('df: {0}'.format(df))
# Shuffle Pandas data frame
import sklearn.utils
df = sklearn.utils.shuffle(df)
print('\n\ndf: {0}'.format(df))
输出:
df: A B
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
df: A B
1 1 1
0 0 0
3 3 3
4 4 4
2 2 2
然后,您可以使用df.reset_index()
重置索引列,如果需要:
df = df.reset_index(drop=True)
print('\n\ndf: {0}'.format(df)
输出:
df: A B
0 1 1
1 0 0
2 4 4
3 2 2
4 3 3
答案 4 :(得分:6)
从文档中使用sample()
:
In [79]: s = pd.Series([0,1,2,3,4,5])
# When no arguments are passed, returns 1 row.
In [80]: s.sample()
Out[80]:
0 0
dtype: int64
# One may specify either a number of rows:
In [81]: s.sample(n=3)
Out[81]:
5 5
2 2
4 4
dtype: int64
# Or a fraction of the rows:
In [82]: s.sample(frac=0.5)
Out[82]:
5 5
4 4
1 1
dtype: int64
答案 5 :(得分:3)
我采取了稍微调整@root的答案并直接使用原始值。当然,这意味着你失去了进行花哨索引的能力,但它只是在改组数据时非常有效。
In [1]: import numpy
In [2]: import pandas
In [3]: df = pandas.DataFrame({"A": range(10), "B": range(10)})
In [4]: %timeit df.apply(numpy.random.shuffle, axis=0)
1000 loops, best of 3: 406 µs per loop
In [5]: %%timeit
...: for view in numpy.rollaxis(df.values, 1):
...: numpy.random.shuffle(view)
...:
10000 loops, best of 3: 22.8 µs per loop
In [6]: %timeit df.apply(numpy.random.shuffle, axis=1)
1000 loops, best of 3: 746 µs per loop
In [7]: %%timeit
for view in numpy.rollaxis(df.values, 0):
numpy.random.shuffle(view)
...:
10000 loops, best of 3: 23.4 µs per loop
请注意numpy.rollaxis
将指定的轴带到第一个维度,然后让我们使用剩余的维度迭代数组,即,如果我们想要沿着第一个维度(列)进行混洗,我们需要滚动前面的第二个维度,以便我们将混洗应用于第一维的视图。
In [8]: numpy.rollaxis(df, 0).shape
Out[8]: (10, 2) # we can iterate over 10 arrays with shape (2,) (rows)
In [9]: numpy.rollaxis(df, 1).shape
Out[9]: (2, 10) # we can iterate over 2 arrays with shape (10,) (columns)
然后你的最终函数使用一个技巧使结果符合将函数应用于轴的期望:
def shuffle(df, n=1, axis=0):
df = df.copy()
axis = int(not axis) # pandas.DataFrame is always 2D
for _ in range(n):
for view in numpy.rollaxis(df.values, axis):
numpy.random.shuffle(view)
return df
答案 6 :(得分:2)
当你想要对你的索引进行洗牌时,这可能会更有用。
def shuffle(df):
index = list(df.index)
random.shuffle(index)
df = df.ix[index]
df.reset_index()
return df
使用新索引选择新的df,然后重置它们。
答案 7 :(得分:1)
pandas中的一个简单解决方案是在每列上独立使用sample
方法。使用apply
迭代每列:
df = pd.DataFrame({'a':[1,2,3,4,5,6], 'b':[1,2,3,4,5,6]})
df
a b
0 1 1
1 2 2
2 3 3
3 4 4
4 5 5
5 6 6
df.apply(lambda x: x.sample(frac=1).values)
a b
0 4 2
1 1 6
2 6 5
3 5 3
4 2 4
5 3 1
您必须使用.value
以便返回一个numpy数组而不是系列,否则返回的Series将与原始DataFrame对齐而不更改一个东西:
df.apply(lambda x: x.sample(frac=1))
a b
0 1 1
1 2 2
2 3 3
3 4 4
4 5 5
5 6 6
答案 8 :(得分:0)
如果你只想改组DataFrame的一个子集,我发现这是一个解决方法:
shuffle_to_index = 20
df = pd.concat([df.iloc[np.random.permutation(range(shuffle_to_index))], df.iloc[shuffle_to_index:]])
答案 9 :(得分:0)
我知道问题是pandas
df,但是如果按行发生洗牌(列顺序改变,行顺序不变),则列名称不再重要,使用起来可能很有趣取而代之的是np.array
,然后np.apply_along_axis()
将成为您的目标。
如果这是可以接受的,那么这将是有帮助的,请注意,可以很容易地切换数据被随机排列的轴。
如果您的熊猫数据框名为df
,您可以:
values = df.values
,np.array
values
np.array
进行随机播放
np.array
a = np.array([[10, 11, 12], [20, 21, 22], [30, 31, 32],[40, 41, 42]])
print(a)
[[10 11 12]
[20 21 22]
[30 31 32]
[40 41 42]]
print(np.apply_along_axis(np.random.permutation, 1, a))
[[11 12 10]
[22 21 20]
[31 30 32]
[40 41 42]]
print(np.apply_along_axis(np.random.permutation, 0, a))
[[40 41 32]
[20 31 42]
[10 11 12]
[30 21 22]]
print(a)
[[10 11 12]
[20 21 22]
[30 31 32]
[40 41 42]]