Creating tuples with np.zero

10,299

Solution 1

You could go the structured array route:

In [304]: np.zeros((10,),dtype='i,i,i')
Out[304]: 
array([(0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0),
       (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0)], 
      dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])

Strictly speaking these are not tuples - it just displays them as tuples.

But to get a list of tuples, just use tolist:

In [305]: np.zeros((10,),dtype='i,i,i').tolist()
Out[305]: 
[(0, 0, 0),
 (0, 0, 0),
 (0, 0, 0),
 ...
 (0, 0, 0),
 (0, 0, 0),
 (0, 0, 0)]

You can generalize the tuple length with a string generated with ','.join(['i']*3)

For a non-structured approach I would use

[tuple(x) for x in np.zeros((10,3),int)]

In Python3 (especially) I prefer a list comprehension over the equivalent map: list(map(tuple, np.zeros((10,3),int))).

Some timings (L=10**5):

structured array:

In [340]: timeit np.zeros((L,),dtype='i,i,i')
10000 loops, best of 3: 77.5 µs per loop

structured array converted to list of tuples:

In [341]: timeit np.zeros((L,),dtype='i,i,i').tolist()
10 loops, best of 3: 73.6 ms per loop

list of tuples from 2d array:

In [342]: timeit [tuple(x) for x in np.zeros((L,3),int)]
1 loops, best of 3: 223 ms per loop

pure python list of tuples:

In [343]: timeit [(0,0,0) for _ in range(L)]
100 loops, best of 3: 15.1 ms per loop

best list of tuples (@swensel):

In [344]: timeit [(0,0,0)]*L
1000 loops, best of 3: 429 µs per loop

If the ultimate goal is a list of tuples, stick with Python.

If the goal is a numpy structured array, go direct.


One thing to be wary about when using [(0,0,0)]*L; this achieves its speed by simply replicating the pointers. Each entry in the list points to the same tuple. With nested lists that can have serious problems:

x = [[0,0,0]]*L
x[1][1] = 3

changes every sublist. With tuples this isn't so much an issue because they are immutable.

Solution 2

You can use numpy.zeros :

>>> import numpy as np
>>> np.zeros(4*3).reshape(4,3)
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])

And if you want it as tuple :

>>> map(tuple,np.zeros(4*3).reshape(4,3))
[(0.0, 0.0, 0.0), (0.0, 0.0, 0.0), (0.0, 0.0, 0.0), (0.0, 0.0, 0.0)]

Or as @Divakar mentioned in comment as a more elegant way use a costume shape within zeros function :

map(tuple,np.zeros((4,3),dtype=int))

Solution 3

If all you need is a list of tuples, you should stick with plain python, numpy won't speed things up because you need to translate back and forth between numpy arrays and lists/tuples.

This one should be fast enough:

def mkTuples(x, L):
    return [(0,)*L]*x

Comparison:

In [1]: import numpy as np

In [2]: x, L = 10**5, 4

In [3]: %timeit map(tuple, np.zeros((x,L)))
10 loops, best of 3: 177 ms per loop

In [4]: %timeit [(0,)*L]*x
1000 loops, best of 3: 1.07 ms per loop

If it has to be a numpy array, you could do this:

a = np.emtpy(x, dtype=tuple)
a[:] = ((0,)*L,)

Which roughly has the same speed as the plain python version but will result in a numpy array containing tuples.

I wish np.full(x, (0,)*L, dtype=tuple) would work but numpy WANTS to broadcast the second parameter even though it actually corresponds to one entry. Wrapping it into another tuple like above also doesn't work.

Solution 4

You can try this with numpy.zeros

import numpy
a = numpy.zeros(shape=(5,2), dtype=numpy.int)
In [6]: a
Out[6]: 
array([[0, 0],
       [0, 0],
       [0, 0],
       [0, 0],
       [0, 0]])

And for tuple, you can do:

map(tuple, numpy.zeros(shape=(5,2)))
Out[3]: [(0.0, 0.0), (0.0, 0.0), (0.0, 0.0), (0.0, 0.0), (0.0, 0.0)]

For datatype int, you can use:

map(tuple, numpy.zeros(shape=(5,2), dtype=numpy.int))
Out[4]: [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]
Share:
10,299
xtlc
Author by

xtlc

Updated on June 04, 2022

Comments

  • xtlc
    xtlc almost 2 years

    I might just be too stupid, but I need a fast version for this:

    for i in range(0,4):
        c.append((0,0,0))
    
    out: [(0,0,0),(0,0,0),(0,0,0),(0,0,0)] 
    

    I want to create a zero filled tuple in the shape of (xL,) with x being the amount of (0,0,0)'s ... I now do have three working solutions, none of them includes np.zero