【问题标题】:Shuffle only specific columns "vertically" in multidimensional array仅在多维数组中“垂直”打乱特定列
【发布时间】:2020-02-28 14:40:52
【问题描述】:

我有一个 6 列的多维数组,例如:

[59, '591', '592', '593', '594', 1582823720],
[9, '91', '92', '93', '94', 1582823745],
[7, '71', '72', '73', '74', 1582823745],
[61, '611', '612', '613', '614', 1582823752],
[54, '541', '542', '543', '544', 1582823717],
[24, '241', '242', '243', '244', 1582823706]

是否有一种简单的方法可以“垂直”地仅对特定列进行洗牌,同时保持其他列内容不变?

例如上面的例子,假设我只需要“垂直”打乱第 2-5 列,而将第 1 列和第 6 列保持原样,所以结果将是:

[59, '541', '242', '243', '74', 1582823720],
[9, '591', '542', '593', '94', 1582823745],
[7, '241', '612', '543', '614', 1582823745],
[61, '611', '92', '73', '544', 1582823752],
[54, '71', '72', '613', '594', 1582823717],
[24, '91', '592', '93', '244', 1582823706]

我是 Python 新手,也许有一个简单的内置解决方案或某个模块可以做到这一点?

我遇到了numpy 库,它使用random.shuffle() 函数可以“垂直”调整整个数组行变得轻而易举,也许有一个可以只调整特定列?

【问题讨论】:

  • 对于矢量化解决方案:a[:,1:5] = shuffle_along_axis(a[:,1:5], axis=0) from stackoverflow.com/a/55317373.
  • @Divikar 在尝试使用shuffle_along_axis 函数时遇到TypeError: list indices must be integers or slices, not tuple 错误...
  • 是的,我假设输入 a 是一个数组,正如您在问题中提到的 multidimensional array

标签: python arrays numpy multidimensional-array shuffle


【解决方案1】:

你可以用 numpy shuffle 函数来做到这一点

x=np.array(yourlist)    
np.random.shuffle(x[:,1:5])

对于水平随机播放,您可以使用转置

np.random.shuffle(x.T[:,1:5])

垂直洗牌示例

x = np.arange(36).reshape(6,6)
x
array([[ 0,  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]])
np.random.shuffle(x[:,1:5])
x
array([[ 0,  7,  8,  9, 10,  5],
       [ 6,  1,  2,  3,  4, 11],
       [12, 19, 20, 21, 22, 17],
       [18, 25, 26, 27, 28, 23],
       [24, 13, 14, 15, 16, 29],
       [30, 31, 32, 33, 34, 35]])

【讨论】:

  • 这似乎将 2-5 列打乱为一整行块,我需要将每一列单独打乱,如示例输出所示。
  • 不,它没有。它单独打乱每个列。检查我添加的示例
【解决方案2】:

这是一个使用 numpy 的代码。

data = [[59, '541', '242', '243', '74', 1582823720],
    [9, '591', '542', '593', '94', 1582823745],
    [7, '241', '612', '543', '614', 1582823745],
    [61, '611', '92', '73', '544', 1582823752],
    [54, '71', '72', '613', '594', 1582823717],
    [24, '91', '592', '93', '244', 1582823706]
]


import numpy as np
import random 


data_numpy = np.array(data)


def shuffle_column(matrix, col_index_to_shuffle):
  """
  """
  current_data = matrix[:, col_index_to_shuffle]
  random.shuffle(current_data)
  matrix[:, col_index_to_shuffle] = current_data
  return matrix


shuffled_matrix = shuffle_column(data_numpy, 2)
shuffled_matrix

array([['59', '541', '242', '243', '74', '1582823720'],
       ['9', '591', '92', '593', '94', '1582823745'],
       ['7', '241', '592', '543', '614', '1582823745'],
       ['61', '611', '612', '73', '544', '1582823752'],
       ['54', '71', '72', '613', '594', '1582823717'],
       ['24', '91', '542', '93', '244', '1582823706']], dtype='<U21')

【讨论】:

    【解决方案3】:

    我不确定这是否存在于其他库中,尽管我相信这样的功能应该存在。但是,我不需要numpy 来做到这一点:

    • 转置数组。
    • 随机排列您需要的子数组。
    • 将数组转回。

    洗牌第四列的代码示例是:

    import random
    # I am using pprint to beautify the output on the terminal
    from pprint import pprint
    arr = [[59, '591', '592', '593', '594', 1582823720],
           [9, '91', '92', '93', '94', 1582823745],
           [7, '71', '72', '73', '74', 1582823745],
           [61, '611', '612', '613', '614', 1582823752],
           [54, '541', '542', '543', '544', 1582823717],
           [24, '241', '242', '243', '244', 1582823706]
          ]
    t_arr = [*zip(*arr)]
    # I am converting array elements to lists as the zip() function produce tuples instead of lists.
    t_arr = [list(sub_arr) for sub_arr in t_arr]
    random.shuffle(t_arr[3])
    arr_b = [*zip(*t_arr)]
    # Again, converting back to lists
    arr_b = [list(sub_arr) for sub_arr in arr_b]
    # printing out the results :)
    pprint(arr_b)
    

    这是输出:

    [[59, '591', '592', '73', '594', 1582823720],
     [9, '91', '92', '243', '94', 1582823745],
     [7, '71', '72', '543', '74', 1582823745],
     [61, '611', '612', '93', '614', 1582823752],
     [54, '541', '542', '613', '544', 1582823717],
     [24, '241', '242', '593', '244', 1582823706]]
    

    【讨论】:

      【解决方案4】:

      numpy shuffle 可以就地打乱子数组。

      如果你想让 4 列保持它们的水平一致性,就这样做

      data = np.array(data)
      np.random.shuffle(data[1:5])
      

      前面有np.random.seed(0),它给出了

      array([['59', '591', '592', '593', '594', '1582823720'],
             ['61', '611', '612', '613', '614', '1582823752'],
             ['54', '541', '542', '543', '544', '1582823717'],
             ['7', '71', '72', '73', '74', '1582823745'],
             ['9', '91', '92', '93', '94', '1582823745'],
             ['24', '241', '242', '243', '244', '1582823706']], dtype='<U11')
      

      如果您希望列单独打乱:

      data = np.array(data)
      tdata = np.transpose(tdata)
      for i in range(1,5): np.shuffle(tdata[i])
      data = np.transpose(tdata)
      

      前面有np.random.seed(0),它给出了

      array([['59', '241', '92', '613', '244', '1582823720'],
             ['9', '71', '612', '243', '74', '1582823745'],
             ['7', '91', '542', '93', '614', '1582823745'],
             ['61', '611', '592', '73', '544', '1582823752'],
             ['54', '591', '72', '543', '94', '1582823717'],
             ['24', '541', '242', '593', '594', '1582823706']], dtype='<U11')
      

      【讨论】:

      • 我所追求的是“要单独洗牌的列”的情况,并且您的代码似乎可以工作,但是似乎拼写错误很少:第二行应以 data 作为参数而不是 @ 987654328@,第三行应该是np.random.shuffle 而不是np.shuffle 至于你的第一个“水平一致性”案例,它似乎只在我包含data[:,1:5]作为随机参数时才有效。
      猜你喜欢
      • 2020-09-28
      • 1970-01-01
      • 2019-02-12
      • 1970-01-01
      • 2012-02-22
      • 1970-01-01
      • 2018-06-25
      • 1970-01-01
      • 2013-05-01
      相关资源
      最近更新 更多