1

I have the following array:

values = [1, 1, 1, [1,2], 1,[3,4,5],[6,7]]

I'd like to multiply every number inside it by 5. The following code didn't work:

import numpy as np
m = np.array(values)
print(m * 5)

output:

[5 5 5 list([1, 2, 1, 2, 1, 2, 1, 2, 1, 2]) 5
 list([3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5])
 list([6, 7, 6, 7, 6, 7, 6, 7, 6, 7])]
1
  • 3
    You must process the inner lists separately. Numpy isn't very suitable for this task. Commented Aug 19, 2020 at 19:30

4 Answers 4

2

As mentioned in the comments, numpy is bad at this because numpy is designed for arrays of equal length in each dimension: you can't convert your list to a numpy array. BUT this is EXACTLY what the awkward package is designed to do: see https://github.com/scikit-hep/awkward-1.0#readme

Install with pip install awkward1

Then:

import awkward1 as ak

values = [1, 1, 1, [1,2], 1,[3,4,5],[6,7]]
result = ak.Array(values) * 5
print(result.tolist())

yields

[5, 5, 5, [5, 10], 5, [15, 20, 25], [30, 35]]
Sign up to request clarification or add additional context in comments.

Comments

1

Another way to do the trick would be a good old-fashioned recursive function:

values = [1, 1, 1, [1,2], 1,[3,4,5],[6,7]]

def listmult(x, c): 
   out = [] 
   for v in x: 
       if isinstance(v, list): 
           out.append(listmult(v, c)) 
       else: 
           out.append(v*c)
   return out
           
print(listmult(values, 5))

[5, 5, 5, [5, 10], 5, [15, 20, 25], [30, 35]]

Comments

1
In [232]: alist = [1, 1, 1, [1,2], 1,[3,4,5],[6,7]]                                                  

As of 1.19 numpy warns about making an array from such as list:

In [233]: np.array(alist)                                                                            
/usr/local/bin/ipython3:1: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
  #!/usr/bin/python3
Out[233]: 
array([1, 1, 1, list([1, 2]), 1, list([3, 4, 5]), list([6, 7])],
      dtype=object)

Notice that this array contains numbers and lists:

In [234]: np.array(alist, object)                                                                    
Out[234]: 
array([1, 1, 1, list([1, 2]), 1, list([3, 4, 5]), list([6, 7])],
      dtype=object)

For an object dtype array, it iterates (at python speed) over the elements, and delegates the action to the element's own method. For a list *5 means replicate:

In [235]: np.array(alist, object)*5                                                                  
Out[235]: 
array([5, 5, 5, list([1, 2, 1, 2, 1, 2, 1, 2, 1, 2]), 5,
       list([3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5]),
       list([6, 7, 6, 7, 6, 7, 6, 7, 6, 7])], dtype=object)

Now if the list contained arrays instead of lists:

In [236]: alist = [1, 1, 1, np.array([1,2]), 1,np.array([3,4,5]),np.array([6,7])]                    
In [237]: np.array(alist, object)                                                                    
Out[237]: 
array([1, 1, 1, array([1, 2]), 1, array([3, 4, 5]), array([6, 7])],
      dtype=object)

now the multiplication works for the array elements - with the numeric multiply.

In [238]: np.array(alist, object)*5                                                                  
Out[238]: 
array([5, 5, 5, array([ 5, 10]), 5, array([15, 20, 25]), array([30, 35])],
      dtype=object)

Math on object dtype arrays is hit-or-miss, depending on the type of the elements. It works for some, not for others, depending on how the operation is implemented by the elements. And even where it works, the speed is more like a list comprehension than a multidimensional array.

In [244]: timeit np.array(alist, object)*5                                                           
13.3 µs ± 333 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [245]: timeit [i*5 for i in alist]                                                                
6.43 µs ± 140 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [246]: timeit np.array([i*5 for i in alist],object)                                               
9.98 µs ± 47.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Comments

0

I'm afraid your data structure doesn't allow that operation. At least not with numpy. If you cast a list of lists of different dimensionality to a numpy array, the resulting data type will be object but no numeric data type (int, float, etc.):

>>> import numpy as np
>>> np.array([1, [1]])
array([1, list([1])], dtype=object)

Thus, numpy doesn't see the content in your array as numerical and therefore can't broadcast numerical operations. Make sure to have equal dimensionality in all input data so that after converting your list of lists to a numpy array the dtype is a numerical data type:

>>> np.array([[1], [1]]).dtype
dtype('int64')

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.