1

Using the example given here:

dt = np.dtype([('name', np.unicode_, 16), ('grades', np.float64, (2,))])
x = np.array([('Sarah', (8.0, 7.0)), ('John', (6.0, 7.0))], dtype=dt)

How can I access only the grades at say position 0 in the 'grades' array?

Because of the ambiguitiy of how I can access the grades of a specific person, i.e. because I can either write

>>> x['grades'][0]
>>> [8.0 7.0]

or

>>> x[0]['grades']
>>> [8.0 7.0]

which will both give the same result, I don't see any way for how I would be able to only access the grade at position 0, but for all the persons. Is there a way?

I cannot write

>>> x[0]['grades'][0]
>>> 8.0

or some combination like this

>>> x[:]['grades'][0]
>>> x[0]['grades'][:]

On the same note: Why is the shape of the 'grades' field declared as '(2,)', while '(2)', '[2,]', '[2]' and '2' all seem to give the same results?

mapf
  • 1,906
  • 1
  • 14
  • 40
  • 1
    `shape` is a tuple. The proper display of a 1 element tuple is `(2,)`. `(2)` is just the number 2, the `()` are a grouping tool, and ignored in not needed. `[2]` is a 1 element list. Often `2`, `[2]` and `(2,)` work the same, but sometimes the distinction between number, list and tuple is significant. – hpaulj Feb 27 '19 at 17:46
  • I see thank you! I will stick with the proper display then. – mapf Feb 28 '19 at 09:30

1 Answers1

3

This will print, for each person, the first grade from grades:

print (x[:]['grades'][:,0])

Alternatively:

print(x['grades'][:,0])

Output:

[8. 6.]

Explanation:

  1. x[:]['grades'] (or x['grades']) produces a 2d array. Actually, it produces a 1d array of the values of grade, but then each value of grade is itself a 1d array. Net result, a 2d array:

    [[8. 7.] [6. 7.]]

  2. From this 2d array, we want to get only the first grade from each grade for all grades, so we then use the indexing [:,0]

fountainhead
  • 3,584
  • 1
  • 8
  • 17
  • Great answer, thank you so much! Do you also have an explanation for my follow-up question? – mapf Feb 27 '19 at 16:25
  • 1
    @mapf: You're welcome. I'm afraid, I'm also stumped by why `(2)`, `[2,]`, `[2]` and `2` , all produce the same result as `(2,)`. But you can be sure that no harm can ever come to you if you strictly follow the `(n,)` notation for a 1d shape. Shapes are always supposed to be represented by tuples, and it is the presence of **one or more commas** that makes something a tuple -- not the presence of parentheses. – fountainhead Feb 27 '19 at 17:00
  • 1
    Incidentally, the doc page you've referred to in your post, also has an example, where they create a 1d sub-array by specifying just `4` instead of `(4,)`. So, whoever wrote that page is probably aware of this flexibility. As I said, it is always safe to stick to the `(n,)` notation for a 1d shape. – fountainhead Feb 27 '19 at 17:04
  • I see, thank you so much for the insight. I didn't know about the (n, ) notation or that the comma makes the touple. Very interesting! – mapf Feb 28 '19 at 09:21
  • 1
    It also helps to recall that given any expression (say`x+y`) enclosing the expression in parentheses, as in `(x+y)` is only helpful in enforcing **operator precedence** (you want the `+` to be performed first). The parentheses doesn't result in a tuple. If you wanted that to become a tuple with a single value, you'd be using `((x+y),)`, or, whenever dropping the outer parentheses doesn't result in syntactic ambiguity, you could also be using `(x+y),` (with a comma, but no outer parentheses). – fountainhead Feb 28 '19 at 09:43
  • I always thought that python would have a different understanding of / would distinguish between parentheses in calculations and parentheses when defining something. But I guess this makes more sense! Also, I assumed that the parentheses make the touple, just as the square brackets and the curly brackets make the list and dict respectively. But apparently that is a common misconception. – mapf Feb 28 '19 at 10:50