9

I'd like to know if it's possible to apply a function (or juste an operation, such as replacing values) to column in a python 2d array, without using for loops.

I'm sorry if the question has already been asked, but I couldn't find anything specific about my problem.

I'd like to do something like :

array[:][2] = 1

Which would mean put 1 for each value at the third column, or

func(array[:][2])

Which would mean apply func() to the third column of array.

Is there any magic python-way to do it ?

EDIT : The truth has been spoken. I forgot to say that I didn't want to avoid for() statement to improve performance, but just because I don't wan to add multiples lines for this precise instance. We got 2 answers here, one in a native way, and two more with the help of Numpy. Thanks a lot for your answers !

Coulis
  • 196
  • 1
  • 13

4 Answers4

7

You can do this easily with numpy arrays. Example -

In [2]: import numpy as np

In [3]: na = np.array([[1,2,3],[3,4,5]])

In [4]: na
Out[4]:
array([[1, 2, 3],
       [3, 4, 5]])

In [5]: na[:,2] = 10

In [6]: na
Out[6]:
array([[ 1,  2, 10],
       [ 3,  4, 10]])

In [7]: na[:,2]
Out[7]: array([10, 10])

In [8]: def func(a):
   ...:     for i,x in enumerate(a):
   ...:         a[i] = x + 1
   ...:

In [9]: na
Out[9]:
array([[ 1,  2, 10],
       [ 3,  4, 10]])

In [10]: func(na[:,1])

In [11]: na
Out[11]:
array([[ 1,  3, 10],
       [ 3,  5, 10]])

You can find more details about this here . Please do be careful , for numpy arrays, as stated in documentation -

All arrays generated by basic slicing are always views of the original array.

This is why when changing the sliced array inside the function, the actual array got changed.

Anand S Kumar
  • 88,551
  • 18
  • 188
  • 176
7

Without numpy it can be done like this:

map(lambda x: x[:2] + [1] + x[3:], array)

map(lambda x: x[:2] + my_func(x[2]) + x[3:], array)
Eugene Soldatov
  • 9,755
  • 2
  • 35
  • 43
2

It would be very simple in numpy and you can do it with a simple assignment :

>>> numpy.array[:,column_number]=value

But if you are looking for a python approach you can use zip function and itertools.repeat():

>>> from itertools import repeat
>>> def replacer(l,index,value):
...     z=zip(*l)
...     z[index]=list(repeat(value,len(l)))
...     return zip(*z)

Demo:

>>> l=[range(4) for _ in range(3)]
>>> replacer(l,2,'*')
[(0, 1, '*', 3), (0, 1, '*', 3), (0, 1, '*', 3)]

Note that since in python 3.X zip returns an iterator you can use list function to return a list also since iterators doesn't support indexing inside the function you need to call the list too.

>>> def replacer(l,index,value):
...     z=list(zip(*l))
...     z[index]=list(repeat(value,len(l)))
...     return zip(*z)

>>> list(replacer(l,2,'*'))
[(0, 1, '*', 3), (0, 1, '*', 3), (0, 1, '*', 3)]
Mazdak
  • 105,000
  • 18
  • 159
  • 188
  • Sorry for the LONG delay, but I'd like to know something. Is it a good practice to use libraries such as numpy, scipy, etc. for a game ? This array problem was about the map initialization for a 2d game, but I was wondering if it was " good " to use scientific libraries to lighten my code. – Coulis Oct 06 '15 at 12:14
2

you can map a function to each column....

ar = [[1,2,3],
      [3,4,5],
      [3,4,5],
      [3,4,5],
      [3,4,5]]

if you want change second column to 100:

    def column_change(l,n =1 , m =100):
        l[n] = m
        return l

   print(list(map(colum_change,ar)))

    [[1, 100, 3], [3, 100, 5], [3, 100, 5], [3, 100, 5], [3, 100, 5]]
LetzerWille
  • 5,355
  • 4
  • 23
  • 26