как понять такой случайный код данных в Numpy - PullRequest
0 голосов
/ 27 марта 2019

Я учусь на Numpy и хочу понять такой код перетасовки данных следующим образом:

# x is a m*n np.array
# return a shuffled-rows array 
def shuffle_col_vals(x):
    rand_x = np.array([np.random.choice(x.shape[0], size=x.shape[0], replace=False) for i in range(x.shape[1])]).T
    grid = np.indices(x.shape)
    rand_y = grid[1]
    return x[(rand_x, rand_y)]

Итак, я ввожу np.array объект следующим образом:

x1 = np.array([[1, 2, 3, 4],
                [5, 6, 7, 8],
                [9, 10, 11, 12],
                [13, 14, 15, 16]], dtype=int)

И я получаю вывод shuffle_col_vals(x1), как комментарии, как показано ниже:

array([[ 1,  5, 11, 15],
       [ 3,  8,  9, 14],
       [ 4,  6, 12, 16],
       [ 2,  7, 10, 13]], dtype=int64)

Я запутался в начальном способе rand_x, и я не получил такой способ в numpy.array
И я долго об этом думал, но до сих пор не понимаю, почему return x[(rand_x, rand_y)] получит массив перемешанных строк.
Если не возражаете, кто-нибудь может объяснить мне код?
Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 27 марта 2019

См. Вывод:

import numpy as np


def shuffle_col_val(x):
    print("----------------------------\n   A    rand_x\n")
    f = np.random.choice(x.shape[0], size=x.shape[0], replace=False)
    print(f, "\nNow I transpose an array.")
    rand_x = np.array([f]).T
    print(rand_x)
    print("----------------------------\n    B    rand_y\n")
    print("Grid gives you two possibilities\n you choose second:")
    grid = np.indices(x.shape)
    print(format(grid))
    rand_y = grid[1]
    print("\n----------------------------\n  C  Our rand_x, rand_y:")
    print("\nThe order of values in the column CHANGE:\n  has random order\n{}".format(rand_x))
    print("\nThe order of values in the row NO CHANGE:\n  has normal order 0, 1, 2, 3\n{}".format(rand_y))
    return x[(rand_x, rand_y)]


x1 = np.array([[1, 2, 3, 4],
               [5, 6, 7, 8],
               [9, 10, 11, 12],
               [13, 14, 15, 16]], dtype=int)
print("\n----------------------------\n  D   Our shuffled-rows: \n{}\n".format(shuffle_col_val(x1)))

Вывод:

   A    rand_x
[2 3 0 1] 
Now I transpose an array.
[[2]
 [3]
 [0]
 [1]]
----------------------------
    B    rand_y
Grid gives you two possibilities, you choose second:
[[[0 0 0 0]
  [1 1 1 1]
  [2 2 2 2]
  [3 3 3 3]]

 [[0 1 2 3]
  [0 1 2 3]
  [0 1 2 3]
  [0 1 2 3]]]
----------------------------
  C  Our rand_x, rand_y:
The order of values in the column CHANGE: has random order
[[2]
 [3]
 [0]
 [1]]
The order of values in the row NO CHANGE: has normal order 0, 1, 2, 3
[[0 1 2 3]
 [0 1 2 3]
 [0 1 2 3]
 [0 1 2 3]]
----------------------------
  D   Our shuffled-rows: 
[[ 9 10 11 12]
 [13 14 15 16]
 [ 1  2  3  4]
 [ 5  6  7  8]]
1 голос
/ 27 марта 2019

При индексации массивов Numpy вы можете использовать отдельные элементы.Давайте использовать массив 3x4, чтобы иметь возможность различать оси:

In [1]: x1 = np.array([[1, 2, 3, 4],
   ...:                [5, 6, 7, 8],
   ...:                [9, 10, 11, 12]], dtype=int)

In [2]: x1[0, 0]
Out[2]: 1

Если вы просмотрите Numpy Advanced indexing , вы обнаружите, что вы можете сделать больше в индексировании, предоставляя спискидля каждого измерения.Рассмотрим индексирование с помощью x1[rows..., cols...], давайте возьмем два элемента.

Выбор из первой и второй строки, но всегда из первого столбца:

In [3]: x1[[0, 1], [0, 0]]
Out[3]: array([1, 5])

Вы даже можете индексировать с помощью массивов:

In [4]: x1[[[0, 0], [1, 1]], [[0, 1], [0, 1]]]
Out[4]:
array([[1, 2],
       [5, 6]])

np.indices создает массив строк и столбцов, который, если используется для индексации, возвращает исходный массив:

In [5]: grid = np.indices(x1.shape)

In [6]: np.alltrue(x1[grid[0], grid[1]] == x1)
Out[6]: True

Теперь, если вы перемешаете значения grid[0] colв противном случае, но оставьте grid[1] как есть, а затем используйте их для индексации, вы получите массив со перемешанными значениями столбцов.

Каждый индексный вектор столбца равен [0, 1, 2].Теперь код перетасовывает эти индексные векторы столбцов для каждого столбца индивидуально и складывает их вместе в rand_x в ту же форму, что и x1.

Создайте один индексный вектор перетасованного столбца:

In [7]: np.random.seed(0)
In [8]: np.random.choice(x1.shape[0], size=x1.shape[0], replace=False)
Out[8]: array([2, 1, 0])

Стекирование выполняется с помощью (псевдокода) стека с [random-index-col-vec for cols in range(x1.shape[1])] и затем транспонированием (.T).

Чтобы сделать его немного понятнее, мы можем переписать i как col и использовать column_stack вместо np.array ([... для столбца]). T:

In [9]: np.random.seed(0)
In [10]: col_list = [np.random.choice(x1.shape[0], size=x1.shape[0], replace=False)
                     for col in range(x1.shape[1])]

In [11]: col_list
Out[11]: [array([2, 1, 0]), array([2, 0, 1]), array([0, 2, 1]), array([2, 0, 1])]

In [12]: rand_x = np.column_stack(col_list)
In [13]: rand_x
Out[13]:
array([[2, 2, 0, 2],
       [1, 0, 2, 0],
       [0, 1, 1, 1]])

In [14]: x1[rand_x, grid[1]]
Out[14]:
array([[ 9, 10,  3, 12],
       [ 5,  2, 11,  4],
       [ 1,  6,  7,  8]])

Примечание:

  • пример вывода, который вы даете, отличается от того, чтоФункция, которую вы предоставляете, делает.Кажется, это транспонировано.
  • использование rand_x и rand_y в примере кода может привести к путанице при использовании для соглашения x = индекс столбца, y = индекс строки
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...