0

How to refer to all rows or a slice for given columns in numpy.ufunc.at

this works for columns:

c = np.array([[1,2,4],[5,3,4]])
np.add.at(c, [[0,1],], 999)
print(c)

out:
[[1000 1001 1003]
 [1004 1002 1003]]

but, these both fail

c = np.array([[1,2,4],[5,3,4]])
np.add.at(c, [,[0,1]], 999)
print(c)

out:
File "<ipython-input-164-ebab6f97aa81>", line 2
np.add.at(c, [,[0,1]], 999)
              ^
SyntaxError: invalid syntax

or

c = np.array([[1,2,4],[5,3,4]])
np.add.at(c, [:,[0,1]], 999)
print(c)
out:
File "<ipython-input-165-cef6394c4870>", line 2
    np.add.at(c, [:,[0,1]], 999)
                  ^
SyntaxError: invalid syntax
figs_and_nuts
  • 4,870
  • 2
  • 31
  • 56

2 Answers2

3

While @Paul has the right fix, a bit of explanation might be in order.

np.add.at(c, [[0,1],], 999)

A trailing comma isn't needed in lists; it is used in tuples to distingish the single item tuple from a simpler () grouping.

In [197]: [[0,1],]
Out[197]: [[0, 1]]
In [198]: ([0,1],)
Out[198]: ([0, 1],)
In [199]: ([0,1])
Out[199]: [0, 1]

So a trailing comma has meaning; but lead one produces an error

In [200]: [,[0,1]]    
SyntaxError: invalid syntax

A : in a list is also an error. : is accepted in an indexing expression, but converted immediately into a slice(None). Indexing uses [] like a list, but isn't the same thing. The 2nd argument of .at is evaluated by Python as a list or tuple, not as an indexing expression.

np.add.at(c, [:,[0,1]], 999)

In [213]: [:,[0,1]]
SyntaxError: invalid syntax

In [215]: np.add.at(c, [slice(None),[0,1]],999)
In [216]: c
Out[216]: 
array([[1000, 1001,    4],
       [1004, 1002,    4]])

The s_ that @Paul suggested works because it is a class with a custom indexing method (__getitem__). It's a cute and convenient trick, but the basic Python syntax that I just described still applies.

In [217]: np.s_[:, [0,1]]
Out[217]: (slice(None, None, None), [0, 1])

As with indexing .at pads with trailing slice(None) as needed, which is why your first example works on rows.

In [224]: np.add.at(c, ([0,1,0], slice(None)),100)
In [225]: c
Out[225]: 
array([[201, 202, 204],
       [105, 103, 104]])
hpaulj
  • 221,503
  • 14
  • 230
  • 353
1

You can use np.s_ like so:

>>> c = np.array([[1,2,4],[5,3,4]])
>>> np.add.at(c, np.s_[:, [0,1]], 999)
>>> c
array([[1000, 1001,    4],
       [1004, 1002,    4]])
Paul Panzer
  • 51,835
  • 3
  • 54
  • 99