2

Is there a easy way to create a numpy.recarray from two lists. For instance, give the following lists:

list1 = ["a","b","c"]
list2 = [1,2,3,4,5,6,7,8,9,10,11,12]

What I am trying to do is to get the following result:

rec_array = np.rec.array([('a', 1), ('a', 2),('a', 3),('a', 4),
                          ('b', 5), ('b', 6),('b', 7),('b', 8),
                          ('c', 9), ('c', 10),('c', 11),('c', 12)] dtype = [('string','|U5'),('int', '<i4')])

I mean I know how a rec.array works but don't really know how to create one from lists. Maybe dicts could make things easy since the key ,value option. But from lists is there a way to do this?.

2
  • 1
    I don't see a pattern in paring items of list1 with list2. There are lots of 'a' values, and only one 'b'. But you can make a structured array from a list of tuples. I'd focus on generating such a list. Commented Apr 21, 2018 at 20:09
  • Oops that was a mistake, already updated Commented Apr 21, 2018 at 20:13

2 Answers 2

1
In [73]: list1 = ["a","b","c"]
    ...: list2 = [1,2,3,4,5,6,7,8,9,10,11,12]
    ...: 
In [74]: dt = [('string','|U5'),('int', '<i4')]

A simple pairing of elements:

In [75]: [(i,j) for i, j in zip(list1,list2)]
Out[75]: [('a', 1), ('b', 2), ('c', 3)]

break list2 into 3 groups:

In [79]: list3 = [list2[i:i+4] for i in range(0,12,4)]
In [80]: list3
Out[80]: [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

double list comprehension:

In [81]: [(i,j) for i,row in zip(list1,list3) for j in row]
Out[81]: 
[('a', 1),
 ('a', 2),
 ('a', 3),
 ('a', 4),
 ('b', 5),
 ('b', 6),
 ('b', 7),
 ('b', 8),
 ('c', 9),
 ('c', 10),
 ('c', 11),
 ('c', 12)]

make a structured array from that:

In [82]: np.array(_, dtype=dt)
Out[82]: 
array([('a',  1), ('a',  2), ('a',  3), ('a',  4), ('b',  5), ('b',  6),
       ('b',  7), ('b',  8), ('c',  9), ('c', 10), ('c', 11), ('c', 12)],
      dtype=[('string', '<U5'), ('int', '<i4')])

OR to make a (3,4) array:

In [86]: [[(i,j) for j in row] for i,row in zip(list1, list3)]
Out[86]: 
[[('a', 1), ('a', 2), ('a', 3), ('a', 4)],
 [('b', 5), ('b', 6), ('b', 7), ('b', 8)],
 [('c', 9), ('c', 10), ('c', 11), ('c', 12)]]
In [87]: np.array(_, dt)
Out[87]: 
array([[('a',  1), ('a',  2), ('a',  3), ('a',  4)],
       [('b',  5), ('b',  6), ('b',  7), ('b',  8)],
       [('c',  9), ('c', 10), ('c', 11), ('c', 12)]],
      dtype=[('string', '<U5'), ('int', '<i4')])
In [88]: _.shape
Out[88]: (3, 4)

Or replicate list1 to same size as list2:

In [97]: np.array([(i,j) for i,j in zip(np.repeat(list1,4),list2)],dt).reshape(3
    ...: ,4)
Out[97]: 
array([[('a',  1), ('a',  2), ('a',  3), ('a',  4)],
       [('b',  5), ('b',  6), ('b',  7), ('b',  8)],
       [('c',  9), ('c', 10), ('c', 11), ('c', 12)]],
      dtype=[('string', '<U5'), ('int', '<i4')])
Sign up to request clarification or add additional context in comments.

Comments

1

In addition to @hpaulj's methods you could also allocate and then fill the array like so:

dtype = [('string','|U5'),('int', '<i4')]
>>> list1 = ["a","b","c"]
>>> list2 = [1,2,3,4,5,6,7,8,9,10,11,12]
>>> 
>>> result = np.recarray((12,), dtype=dtype)
>>> result['string'].reshape(3, 4).T[...] = list1
>>> result['int'] = list2
>>> result
rec.array([('a',  1), ('a',  2), ('a',  3), ('a',  4), ('b',  5),
           ('b',  6), ('b',  7), ('b',  8), ('c',  9), ('c', 10),
           ('c', 11), ('c', 12)],
          dtype=[('string', '<U5'), ('int', '<i4')])

The (small) advantage here is that one can use broadcasting on list1.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.