# NumPy 筆記:平移陣列元素 > 作者:王一哲 > 日期:2019/1/14 </br> ## 前言 今天學生問了一個好玩的問題:**如果使用已經建立了一個二維陣列,要怎麼做才能將所有的元素向某個方向平移?**以下是我找到的作法,請注意,以下的程式碼都省略了 **import numpy as np**。 </br> ## 方法1:使用索引取出元素 ### 產生陣列 首先我們產生一個 $9 \times 8$ 的陣列,為了一眼就看出每個元素原來的位置,我將第0列皆設定為個位數,第1列皆為1開頭,其餘依此類推。 ```python m, n = 9, 8 a = np.zeros(m * n).reshape(m, n) for i in range(m): for j in range(n): a[i][j] = i * 10 + j print(a) ``` 輸出為 ```python [[ 0. 1. 2. 3. 4. 5. 6. 7.] [10. 11. 12. 13. 14. 15. 16. 17.] [20. 21. 22. 23. 24. 25. 26. 27.] [30. 31. 32. 33. 34. 35. 36. 37.] [40. 41. 42. 43. 44. 45. 46. 47.] [50. 51. 52. 53. 54. 55. 56. 57.] [60. 61. 62. 63. 64. 65. 66. 67.] [70. 71. 72. 73. 74. 75. 76. 77.] [80. 81. 82. 83. 84. 85. 86. 87.]] ``` 我們先練習一下取值的方法,如果想要印出陣列中每一列索引值為1到最後1個的元素,語法為 ```python print(a[::, 1:]) ``` 輸出為 ```python [[ 1. 2. 3. 4. 5. 6. 7.] [11. 12. 13. 14. 15. 16. 17.] [21. 22. 23. 24. 25. 26. 27.] [31. 32. 33. 34. 35. 36. 37.] [41. 42. 43. 44. 45. 46. 47.] [51. 52. 53. 54. 55. 56. 57.] [61. 62. 63. 64. 65. 66. 67.] [71. 72. 73. 74. 75. 76. 77.] [81. 82. 83. 84. 85. 86. 87.]] ``` 如果想要印出陣列中每一列索引值為0的元素,語法為 ```python print(a[::, 0]) ``` 輸出為 ```python [ 0. 10. 20. 30. 40. 50. 60. 70. 80.] ``` </br> ### 向左平移1格 我們先產生一個新的陣列 left,用來儲存平移後的資料,再利用索引值將平移後的元素填入對應的位置,語法為 ```python left = np.zeros(m * n).reshape(m, n) left[::, 0:-1] = a[::, 1:] left[::, -1] = a[::, 0] print(left) ``` 輸出為 ```python [[ 1. 2. 3. 4. 5. 6. 7. 0.] [11. 12. 13. 14. 15. 16. 17. 10.] [21. 22. 23. 24. 25. 26. 27. 20.] [31. 32. 33. 34. 35. 36. 37. 30.] [41. 42. 43. 44. 45. 46. 47. 40.] [51. 52. 53. 54. 55. 56. 57. 50.] [61. 62. 63. 64. 65. 66. 67. 60.] [71. 72. 73. 74. 75. 76. 77. 70.] [81. 82. 83. 84. 85. 86. 87. 80.]] ``` </br> ### 向右平移1格 我們先產生一個新的陣列 right,用來儲存平移後的資料,再利用索引值將平移後的元素填入對應的位置,語法為 ```python right = np.zeros(m * n).reshape(m, n) right[::, 1:] = a[::, 0:-1] right[::, 0] = a[::, -1] print(right) ``` 輸出為 ```python [[ 7. 0. 1. 2. 3. 4. 5. 6.] [17. 10. 11. 12. 13. 14. 15. 16.] [27. 20. 21. 22. 23. 24. 25. 26.] [37. 30. 31. 32. 33. 34. 35. 36.] [47. 40. 41. 42. 43. 44. 45. 46.] [57. 50. 51. 52. 53. 54. 55. 56.] [67. 60. 61. 62. 63. 64. 65. 66.] [77. 70. 71. 72. 73. 74. 75. 76.] [87. 80. 81. 82. 83. 84. 85. 86.]] ``` </br> ### 向上平移1格 我們先產生一個新的陣列 top,用來儲存平移後的資料,再利用索引值將平移後的元素填入對應的位置,語法為 ```python top = np.zeros(m * n).reshape(m, n) top[0:-1, ::] = a[1:, ::] top[-1, ::] = a[0, ::] print(top) ``` 輸出為 ```python [[10. 11. 12. 13. 14. 15. 16. 17.] [20. 21. 22. 23. 24. 25. 26. 27.] [30. 31. 32. 33. 34. 35. 36. 37.] [40. 41. 42. 43. 44. 45. 46. 47.] [50. 51. 52. 53. 54. 55. 56. 57.] [60. 61. 62. 63. 64. 65. 66. 67.] [70. 71. 72. 73. 74. 75. 76. 77.] [80. 81. 82. 83. 84. 85. 86. 87.] [ 0. 1. 2. 3. 4. 5. 6. 7.]] ``` </br> ### 向下平移1格 我們先產生一個新的陣列 bottom,用來儲存平移後的資料,再利用索引值將平移後的元素填入對應的位置,語法為 ```python bottom = np.zeros(m * n).reshape(m, n) bottom[1:, ::] = a[0:-1, ::] bottom[0, ::] = a[-1, ::] print(bottom) ``` 輸出為 ```python [[80. 81. 82. 83. 84. 85. 86. 87.] [ 0. 1. 2. 3. 4. 5. 6. 7.] [10. 11. 12. 13. 14. 15. 16. 17.] [20. 21. 22. 23. 24. 25. 26. 27.] [30. 31. 32. 33. 34. 35. 36. 37.] [40. 41. 42. 43. 44. 45. 46. 47.] [50. 51. 52. 53. 54. 55. 56. 57.] [60. 61. 62. 63. 64. 65. 66. 67.] [70. 71. 72. 73. 74. 75. 76. 77.]] ``` </br> ### 同時向左、向上各平移1格 我們先產生一個新的陣列 top_left,用來儲存平移後的資料,再利用索引值將平移後的元素填入對應的位置,語法為 ```python top_left = np.zeros(m * n).reshape(m, n) top_left[0:-1, 0:-1] = a[1:, 1:] # 將陣列a第1列、第1行到右下角的元素填到top_left的左上角 top_left[-1, -1] = a[0, 0] # 將陣列a左上角的元素填到top_left的右下角 top_left[-1, 0:-1] = a[0, 1:] # 將陣列a第0列中除了索引值為1到最後的元素填到top_left的最後1列 top_left[0:-1, -1] = a[1:, 0] # 將陣列a第1列到最後1列中索引值為0的元素填到top_left的最後1行 print(top_left) ``` 輸出為 ```python [[11. 12. 13. 14. 15. 16. 17. 10.] [21. 22. 23. 24. 25. 26. 27. 20.] [31. 32. 33. 34. 35. 36. 37. 30.] [41. 42. 43. 44. 45. 46. 47. 40.] [51. 52. 53. 54. 55. 56. 57. 50.] [61. 62. 63. 64. 65. 66. 67. 60.] [71. 72. 73. 74. 75. 76. 77. 70.] [81. 82. 83. 84. 85. 86. 87. 80.] [ 1. 2. 3. 4. 5. 6. 7. 0.]] ``` </br> ## 方法2:使用 numpy.roll numpy.roll 的語法為 ```python numpy.roll(陣列, 移動格數, axis = 0 或 1) ``` 若 axis = 0 會縱向移動,若 axis = 1 會橫向移動。詳細的說明請參考官方說明書[numpy.roll](https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.roll.html)。以下我們改用 numpy.roll 再做一次平移,由於這樣的寫法與方法1的寫法效果相同,故省略輸出結果。 ### 向左平移1格 ```python left_roll = np.roll(a, -1, axis = 1) print(left_roll) ``` </br> ### 向右平移1格 ```python right_roll = np.roll(a, 1, axis = 1) print(right_roll) ``` </br> ### 向上平移1格 ```python top_roll = np.roll(a, -1, axis = 0) print(top_roll) ``` </br> ### 向下平移1格 ```python bottom_roll = np.roll(a, 1, axis = 0) print(bottom_roll) ``` </br> ### 同時向左、向上各平移1格 ```python roll = np.roll(a, -1, axis = 0) roll = np.roll(roll, -1, axis = 1) print(roll) ``` </br> ## 結語 當我聽到這個問題時,第一個想法是用索引值取出元素再存入對應的位置,也就是方法1。但是我覺得 Numpy 可能有已經寫好的工具,果然搜尋一下就找到了 numpy.roll,Numpy 的工具果然很齊全。 --- ###### tags:`Python`