how to (simply) build a integer and float mixed numpy array

12,407

Solution 1

You could use an array with dtype = object:

>>> arr = np.ndarray((10,4),dtype = object)
>>> arr[:,0] = int(10)
>>> arr[:,1:] = float(10)
>>> arr
array([[10, 10.0, 10.0, 10.0],
       [10, 10.0, 10.0, 10.0],
       [10, 10.0, 10.0, 10.0],
       [10, 10.0, 10.0, 10.0],
       [10, 10.0, 10.0, 10.0],
       [10, 10.0, 10.0, 10.0],
       [10, 10.0, 10.0, 10.0],
       [10, 10.0, 10.0, 10.0],
       [10, 10.0, 10.0, 10.0],
       [10, 10.0, 10.0, 10.0]], dtype=object)

Notice that you get the right behavior when doing arithmetic.

>>> arr / 3
array([[3, 3.33333333333, 3.33333333333, 3.33333333333],
       [3, 3.33333333333, 3.33333333333, 3.33333333333],
       [3, 3.33333333333, 3.33333333333, 3.33333333333],
       [3, 3.33333333333, 3.33333333333, 3.33333333333],
       [3, 3.33333333333, 3.33333333333, 3.33333333333],
       [3, 3.33333333333, 3.33333333333, 3.33333333333],
       [3, 3.33333333333, 3.33333333333, 3.33333333333],
       [3, 3.33333333333, 3.33333333333, 3.33333333333],
       [3, 3.33333333333, 3.33333333333, 3.33333333333],
       [3, 3.33333333333, 3.33333333333, 3.33333333333]], dtype=object)

Or you could use a numpy.recarray:

>>> import numpy as np
>>> arr = np.recarray(10,dtype=[('x',int),('y',float,4)])
>>> arr[:] = 0
>>> arr
rec.array([(0, array([ 0.,  0.,  0.,  0.])), (0, array([ 0.,  0.,  0.,  0.])),
           (0, array([ 0.,  0.,  0.,  0.])), (0, array([ 0.,  0.,  0.,  0.])),
           (0, array([ 0.,  0.,  0.,  0.])), (0, array([ 0.,  0.,  0.,  0.])),
           (0, array([ 0.,  0.,  0.,  0.])), (0, array([ 0.,  0.,  0.,  0.])),
           (0, array([ 0.,  0.,  0.,  0.])), (0, array([ 0.,  0.,  0.,  0.]))], 
  dtype=[('x', '<i4'), ('y', '<f8', (4,))])
>>> arr['x']
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
>>> arr['y']
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.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.]])

If you need to do arithmetic on all the values, you'll have to perform the operation on each field seperately, e.g.

>>> arr['x'] += 2
>>> arr['y'] += 2

Solution 2

Although I can think of lots of reasons why you shouldn't be wanting to do this in the first place, it's not for me to judge, and I hate when people try to diminish the value of my own quick'n'dirty hacks.

The rationale is to use dtype=object. Since everything in Python is an object, you can mixed numeric types while still preserving homogeneity inside an array. I suggest the following, but you can obviously adapt to your needs:

import numpy

rows = 5
a = numpy.zeros((rows,5)).astype(object)
a[:,0] = a[:,0].astype(int)
print a

[[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  0.0  0.0  0.0]
 [0  0.0  0.0  0.0  0.0]]

Solution 3

Read this in the numpy documentation, which indicates all the members have to be of same type

NumPy's main object is the homogeneous multidimensional array. It is a table of elements (usually numbers), all of the same type, indexed by a tuple of positive integers.

Share:
12,407
gluuke
Author by

gluuke

Just a computational material scientist ... ;)

Updated on July 28, 2022

Comments

  • gluuke
    gluuke almost 2 years

    I would simply like to create a numpy array of size(N,m) that has just the first column made of integer, and the rest by default float. So that, if initialized to zero it should be results:

    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.]])
    

    All the attempts I have made return me some tuple sub-elements when trying to create such a structured array.

  • user202729
    user202729 over 2 years
    Although note that dtype=object makes the array as slow (and memory-intensive) as normal Python array.