在numpy数组的每一行中随机调整项目

时间:2018-05-27 16:35:09

标签: python arrays numpy

我有一个如下所示的numpy数组:

import 'package:flutter/material.dart';

void main() {
  runApp(
    new MyApp(),
  );
}

class MyApp extends StatefulWidget {
  const MyApp({
    Key key,
  }) : super(key: key);

  @override
  MyAppState createState() {
    return new MyAppState();
  }
}

class MyAppState extends State<MyApp> {
  MaterialColor _color = Colors.green;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Hello Rectangle',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Hello Rectangle'),
        ),
        body: Column(children: <Widget>[
          HelloRectangle(_color),
          FlatButton(
            child: Text(
              _color == Colors.green ? "Turn Blue" : "Turn Green",
              style: TextStyle(fontSize: 40.0),
              textAlign: TextAlign.center,
            ),
            onPressed: () {
              setState(() {
                _color = _color == Colors.green ? Colors.blue : Colors.green;
              });
            },
          ),
        ]),
      ),
    );
  }
}

class HelloRectangle extends StatefulWidget {
  final Color color;

  HelloRectangle(this.color);

  @override
  HelloRectangleState createState() {
    return new HelloRectangleState();
  }
}

class HelloRectangleState extends State<HelloRectangle> {
  HelloRectangleState();

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: widget.color,
        height: 400.0,
        width: 300.0,
      ),
    );
  }
}

我想分别对每行的项进行随机播放,但不希望每行的shuffle相同(如在几个示例中只是随机播放列顺序)。

例如,我想要一个如下输出:

Xtrain = np.array([[1, 2, 3],
                   [4, 5, 6],
                   [1, 7, 3]])

如何以有效的方式随机随机地随机播放每一行?我的实际np数组超过100000行和1000列。

7 个答案:

答案 0 :(得分:6)

由于您只想对列进行随机播放,因此只需对矩阵的转置执行shuffling即可:

In [172]: def crazyshuffle(arr):
     ...:     x, y = arr.shape
     ...:     rows = np.indices((x,y))[0]
     ...:     cols = [np.random.permutation(y) for _ in range(x)]
     ...:     return arr[rows, cols]
     ...: 

请注意,2D阵列上的random.suffle()会混洗行而不是每行中的项目。即改变行的位置。因此,如果你改变转置矩阵行的位置,你实际上是在改组原始数组的列。

如果你仍然需要一个完全独立的shuffle,你可以为每一行创建随机索引,然后使用简单的索引创建最终数组:

In [173]: crazyshuffle(Xtrain)
Out[173]: 
array([[1, 3, 2],
       [6, 5, 4],
       [7, 3, 1]])

In [174]: crazyshuffle(Xtrain)
Out[174]: 
array([[2, 3, 1],
       [4, 6, 5],
       [1, 3, 7]])

演示:

FIND

答案 1 :(得分:3)

这种解决方案无论如何都没有效率,但我很乐意考虑它,所以写下来。基本上,您对数组进行了ravel,并创建了一个行标签数组和一个索引数组。您将索引数组混洗,并使用该数组索引原始和行标签数组。然后,将稳定 argsort应用于行标签,以将数据收集到行中。应用该索引和重塑和中提琴,数据由行独立混洗:

import numpy as np

r, c = 3, 4  # x.shape

x = np.arange(12) + 1  # Already raveled 
inds = np.arange(x.size)
rows = np.repeat(np.arange(r).reshape(-1, 1), c, axis=1).ravel()

np.random.shuffle(inds)
x = x[inds]
rows = rows[inds]

inds = np.argsort(rows, kind='mergesort')
x = x[inds].reshape(r, c)

这是IDEOne Link

答案 2 :(得分:2)

来自:https://github.com/numpy/numpy/issues/5173

def disarrange(a, axis=-1):
    """
    Shuffle `a` in-place along the given axis.

    Apply numpy.random.shuffle to the given axis of `a`.
    Each one-dimensional slice is shuffled independently.
    """
    b = a.swapaxes(axis, -1)
    # Shuffle `b` in-place along the last axis.  `b` is a view of `a`,
    # so `a` is shuffled in place, too.
    shp = b.shape[:-1]
    for ndx in np.ndindex(shp):
        np.random.shuffle(b[ndx])
    return

答案 3 :(得分:2)

我们可以创建一个随机的二维矩阵,按行排序,然后使用argsort给出的索引矩阵重新排序目标矩阵。

target = np.random.randint(10, size=(5, 5))
# [[7 4 0 2 5]
# [5 6 4 8 7]
# [6 4 7 9 5]
# [8 6 6 2 8]
# [8 1 6 7 3]]

shuffle_helper = np.argsort(np.random.rand(5,5), axis=1)
# [[0 4 3 2 1]
# [4 2 1 3 0]
# [1 2 3 4 0]
# [1 2 4 3 0]
# [1 2 3 0 4]]

target[np.arange(shuffle_helper.shape[0])[:, None], shuffle_helper]
# array([[7, 5, 2, 0, 4],
#       [7, 4, 6, 8, 5],
#       [4, 7, 9, 5, 6],
#       [6, 6, 8, 2, 8],
#       [1, 6, 7, 8, 3]])

<强>解释

  • 我们使用np.random.randargsort来模仿改组的效果。
  • random.rand提供随机性。
  • 然后,我们使用argsortaxis=1来帮助对每一行进行排名。这将创建可用于重新排序的索引。

答案 4 :(得分:1)

假设您有阵列a,其形状为100000 x 1000.

b = np.random.choice(100000 * 1000, (100000, 1000), replace=False)
ind = np.argsort(b, axis=1)
a_shuffled = a[np.arange(100000)[:,np.newaxis], ind]

我不知道这是否比循环更快,因为它需要排序,但是使用此解决方案,您可能会发明更好的东西,例如使用np.argpartition代替np.argsort

答案 5 :(得分:0)

您可以使用Pandas

df = pd.DataFrame(X_train)
_ = df.apply(lambda x: np.random.shuffle(x.values), axis=1, raw=False)
df.values

如果要随机排列列,请将关键字更改为axis=0

答案 6 :(得分:0)

更新numpy> = 1.17.0

现在规范的方法是使用random generatorpermutation()方法。

generator = np.random.default_rng(seed=123)
generator.permutation(Xtrain, axis=1)
array([[1, 3, 2],
       [4, 6, 5],
       [1, 3, 7]])