版权声明: 891584158@qq.com https://blog.csdn.net/qq_21063873/article/details/80860218 </div>
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
<div id="content_views" class="markdown_views prism-atom-one-dark">
<!-- flowchart 箭头图标 勿删 -->
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path></svg>
<h1 id="有关randomshuffle函数的局限性">有关random.shuffle函数的局限性</h1>
刚刚踩的坑,记录一下,万一对别人有帮助呢。
本文重点: random.shuffle千万不要用于二维numpy.array(也就是矩阵)!!!
首先上证据
如下代码:
import random
import numpy as np
a = np.array([[1,2,3,4],
[5,6,7,8]])
random.shuffle(a)
print(a)
- 1
- 2
- 3
- 4
- 5
- 6
可能对应输出:
[[1 2 3 4]
[1 2 3 4]]
- 1
- 2
得到一个错误输出!
查看random.shuffle源码:
def shuffle(self, x, random=None):
"""Shuffle list x in place, and return None.
Optional argument random is a 0-argument function returning a
random float in [0.0, 1.0); if it is the default None, the
standard random.random will be used.
"""
if random is None:
randbelow = self._randbelow
for i in reversed(range(1, len(x))):
# pick an element in x[:i+1] with which to exchange x[i]
j = randbelow(i+1)
x[i], x[j] = x[j], x[i]
else:
_int = int
for i in reversed(range(1, len(x))):
# pick an element in x[:i+1] with which to exchange x[i]
j = _int(random() * (i+1))
x[i], x[j] = x[j], x[i]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
只需要关注其中交换元素操作为 x[i], x[j] = x[j], x[i] (好骚的操作,我之前不知道有这种写法)。
自己写个代码测试一下,这种交换方式对于二维numpy.array会发生什么事情:
import numpy as np
a = np.array([[1,2,3,4],
[5,6,7,8]])
a[0], a[1] = a[1], a[0]
print(a)
- 1
- 2
- 3
- 4
- 5
输出:
[[5 6 7 8]
[5 6 7 8]]
- 1
- 2
显然这种方式不适合numpy.array的行交换(但是二维list就可以使用这种交换方式。可以自行证明,至于原因暂时不知道,求解答)。
打乱numpy.array正确的姿势当然是使用numpy自带的numpy.random.shuffle()
def shuffle(x): # real signature unknown; restored from __doc__
"""
shuffle(x)
Modify a sequence in-place by shuffling its contents.
This function only shuffles the array along the first axis of a
multi-dimensional array. The order of sub-arrays is changed but
their contents remains the same.
Parameters
----------
x : array_like
The array or list to be shuffled.
Returns
-------
None
Examples
--------
>>> arr = np.arange(10)
>>> np.random.shuffle(arr)
>>> arr
[1 7 5 2 9 4 3 6 0 8]
Multi-dimensional arrays are only shuffled along the first axis:
>>> arr = np.arange(9).reshape((3, 3))
>>> np.random.shuffle(arr)
>>> arr
array([[3, 4, 5],
[6, 7, 8],
[0, 1, 2]])
"""
pass
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
注释中Multi-dimensional arrays are only shuffled along the first axis: 多维向量只是沿着第一个坐标轴进行重新排序。