12

I have array of floats, and I want to floor them to nearest integer, so I can use them as indices.

For example:

In [2]: import numpy as np

In [3]: arr = np.random.rand(1, 10) * 10

In [4]: arr
Out[4]:
array([[4.97896461, 0.21473121, 0.13323678, 3.40534157, 5.08995577,
        6.7924586 , 1.82584208, 6.73890807, 2.45590354, 9.85600841]])

In [5]: arr = np.floor(arr)

In [6]: arr
Out[6]: array([[4., 0., 0., 3., 5., 6., 1., 6., 2., 9.]])

In [7]: arr.dtype
Out[7]: dtype('float64')

They are still floats after flooring, is there a way to automatically cast them to integers?

Toothery
  • 155
  • 1
  • 1
  • 10

3 Answers3

14

I am edit answer with @DanielF explanation: "floor doesn't convert to integer, it just gives integer-valued floats, so you still need an astype to change to int" Check this code to understand the solution:

import numpy as np
arr = np.random.rand(1, 10) * 10
print(arr)
arr = np.floor(arr).astype(int)
print(arr)
OUTPUT:
[[2.76753828 8.84095843 2.5537759  5.65017407 7.77493733 6.47403036
  7.72582766 5.03525625 9.75819442 9.10578944]]
[[2 8 2 5 7 6 7 5 9 9]]
Jocker
  • 368
  • 1
  • 7
  • 2
    Try and give some explanation and not just code. Even just starting with "`floor` doesn't convert to integer, it just gives integer-valued `float`s, so you still need an `astype` to change to `int`" will keep the review queue off your back. – Daniel F Nov 23 '20 at 12:32
1

Why not just use:

np.random.randint(1,10)

vegiv
  • 124
  • 1
  • 9
  • 1
    This is close enough to an answer for me not to flag it, but this should probably be a comment once you get those privileges. It's not *really* addressing the question, but could be a parallel solution. – Daniel F Nov 23 '20 at 12:26
  • The arguments `1` and `10` here have a very different meaning to those in `np.random.rand(1, 10)`: there the arguments are the shape of the resulting array; here you're asking for a single result and `1` and `10` give the bounds. It's not at all clear that the OP wants integers in the range 1 through 10. (I've asked for a clarification in a comment.) – Mark Dickinson Nov 23 '20 at 12:47
  • @DanielF Yes this was supposed to be a comment, but could not comment because i havent unlocked it. – vegiv Nov 23 '20 at 17:30
  • @MarkDickinson Well if you use the size parameter you can get an array with a size ( ex: parameters for randint (low=0,high=10,size=10)), And as he wants to use them as indices im guessing that it is a whole number is what i he wants. But I agree he could specify that. – vegiv Nov 23 '20 at 17:34
1

As alternative to changing type after floor division, you can provide an output array of the desired data type to np.floor (and to any other numpy ufunc). For example, imagine you want to convert the output to np.int32, then do the following:

import numpy as np
arr = np.random.rand(1, 10) * 10
out = np.empty_like(arr, dtype=np.int32)
np.floor(arr, out=out, casting='unsafe')

As the casting argument already indicates, you should know what you are doing when casting outputs into different types. However, in your case it is not really unsafe.

Although, I would not call np.floor in your case, because all values are greater than zero. Therefore, the simplest and probably fastest solution to your problem would be a direct casting to integer.

import numpy as np
arr = (np.random.rand(1, 10) * 10).astype(int)
Carlos Horn
  • 1,115
  • 4
  • 17