Swapping columns in a numpy array?

PythonNumpy

Python Problem Overview


from numpy import *
def swap_columns(my_array, col1, col2):
    temp = my_array[:,col1]
    my_array[:,col1] = my_array[:,col2]
    my_array[:,col2] = temp

Then

swap_columns(data, 0, 1)

Doesn't work. However, calling the code directly

temp = my_array[:,0]
my_array[:,0] = my_array[:,1]
my_array[:,1] = temp

Does. Why is this happening and how can I fix it? The Error says "IndexError: 0-d arrays can only use a single () or a list of newaxes (and a single ...) as an index", which implies the arguments aren't ints? I already tried converting the cols to int but that didn't solve it.

Python Solutions


Solution 1 - Python

There are two issues here. The first is that the data you pass to your function apparently isn't a two-dimensional NumPy array -- at least this is what the error message says.

The second issue is that the code does not do what you expect:

my_array = numpy.arange(9).reshape(3, 3)
# array([[0, 1, 2],
#        [3, 4, 5],
#        [6, 7, 8]])
temp = my_array[:, 0]
my_array[:, 0] = my_array[:, 1]
my_array[:, 1] = temp
# array([[1, 1, 2],
#        [4, 4, 5],
#        [7, 7, 8]])

The problem is that Numpy basic slicing does not create copies of the actual data, but rather a view to the same data. To make this work, you either have to copy explicitly

temp = numpy.copy(my_array[:, 0])
my_array[:, 0] = my_array[:, 1]
my_array[:, 1] = temp

or use advanced slicing

my_array[:,[0, 1]] = my_array[:,[1, 0]]

Solution 2 - Python

I find the following the fastest:

my_array[:, 0], my_array[:, 1] = my_array[:, 1], my_array[:, 0].copy()

Time analysis of:

import numpy as np
my_array = np.arange(900).reshape(30, 30)

is as follows:

%timeit my_array[:, 0], my_array[:, 1] = my_array[:, 1], my_array[:, 0].copy()
The slowest run took 15.05 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 1.72 µs per loop

The advanced slicing times are:

%timeit my_array[:,[0, 1]] = my_array[:,[1, 0]]
The slowest run took 7.38 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 6.9 µs per loop

Solution 3 - Python

An elegant way to swap the columns in NumPy is analogy to swapping two variables in Python like so: x, y = y, x.

i, j = 0, 1
A.T[[i, j]] = A.T[[j, i]]  # swap the columns i and j

Suppose you have a numpy array A like this:

array([[ 0., -1.,  0.,  0.],
       [ 0.,  1.,  1.,  1.],
       [ 0.,  0., -1.,  0.],
       [ 0.,  0.,  0., -1.]])

A.T[[0, 1]] = A.T[[1, 0]] will swap the first two columns:

array([[-1.,  0.,  0.,  0.],
       [ 1.,  0.,  1.,  1.],
       [ 0.,  0., -1.,  0.],
       [ 0.,  0.,  0., -1.]])

Solution 4 - Python

Building up on @Sven's answer:

import numpy as np
my_array = np.arange(9).reshape(3, 3)
print my_array

[[0 1 2]
 [3 4 5]
 [6 7 8]]

def swap_cols(arr, frm, to):
    arr[:,[frm, to]] = arr[:,[to, frm]]

swap_cols(my_array, 0, 1)
print my_array

[[1 0 2]
 [4 3 5]
 [7 6 8]]

def swap_rows(arr, frm, to):
    arr[[frm, to],:] = arr[[to, frm],:]

my_array = np.arange(9).reshape(3, 3)
swap_rows(my_array, 0, 2)
print my_array

[[6 7 8]
 [3 4 5]
 [0 1 2]]

Solution 5 - Python

If you want to simultaneously swap columns and assign to a new variable, the most clear and concise way I could figure out how to do it was this:

import numpy as np
test_arr = np.arange(12).reshape(4,3)
swapped = np.concatenate((test_arr[:, [1,0]], test_arr[:, 2:]), axis=1)

Note, if the further columns don't exist it will concatenate an on an empty array, meaning it will just swap the first two columns.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionaudacious ainsleyView Question on Stackoverflow
Solution 1 - PythonSven MarnachView Answer on Stackoverflow
Solution 2 - PythonblazView Answer on Stackoverflow
Solution 3 - PythonJensun RavichandranView Answer on Stackoverflow
Solution 4 - PythonRenaudView Answer on Stackoverflow
Solution 5 - PythonAndrew HolmgrenView Answer on Stackoverflow