64

I have a pandas series series. If I want to get the element-wise floor or ceiling, is there a built in method or do I have to write the function and use apply? I ask because the data is big so I appreciate efficiency. Also this question has not been asked with respect to the Pandas package.

wolfsatthedoor
  • 5,669
  • 14
  • 38
  • 76

4 Answers4

91

You can use NumPy's built in methods to do this: np.ceil(series) or np.floor(series).

Both return a Series object (not an array) so the index information is preserved.

Alex Riley
  • 132,653
  • 39
  • 224
  • 205
23

UPDATE: THIS ANSWER IS WRONG, DO NOT DO THIS

Explanation: using Series.apply() with a native vectorized Numpy function makes no sense in most cases as it will run the Numpy function in a Python loop, leading to much worse performance. You'd be much better off using np.floor(series) directly, as suggested by several other answers.

You could do something like this using NumPy's floor, for instance, with a dataframe:

floored_data = data.apply(np.floor)

Can't test it right now but an actual and working solution might not be far from it.

Jivan
  • 16,401
  • 7
  • 56
  • 89
21

I am the OP, but I tried this and it worked:

np.floor(series)
wolfsatthedoor
  • 5,669
  • 14
  • 38
  • 76
6

clip_lower / clip_upper

With Pandas, you can set a floor via clip_lower or ceiling via clip_upper:

s = pd.Series([-1, 0, -5, 3])

print(s.clip_lower(0))
# 0    0
# 1    0
# 2    0
# 3    3
# dtype: int64

print(s.clip_upper(0))
# 0   -1
# 1    0
# 2   -5
# 3    0
# dtype: int64

clip

pd.Series.clip supports more generalised functionality, e.g. applying and flooring a ceiling simultaneously, e.g. s.clip(-1, 1).

jpp
  • 134,728
  • 29
  • 196
  • 240
  • 5
    I can see that it's worth mentioning `clip` et al. as *somewhat* related functions, but clipping a value is a very different operation to finding the floor/ceiling of that value... – Alex Riley Jan 14 '19 at 13:14
  • @AlexRiley, Point taken; the reason I mention it is there are situations where the upper and lower bounds are variables from an external input, and you may want (for example) to use `s.clip(-1, np.inf)` or `s.clip(-np.inf, 1)` to handle those situations seamlessly. – jpp Jan 14 '19 at 13:15
  • It was more that I was puzzled by what OP's wants to do given the wording of their question (and indeed OP's own answer). Unless I'm missing something, if you have `s = pd.Series([3.1, 2.2, 5.6])` there does not seem to be a way to use `clip` alone to compute the same result as `np.floor(s)` for example. (Not to detract from your answer which is well-written and useful information - I was just confused when I reread the question.) – Alex Riley Jan 14 '19 at 13:24
  • 1
    @AlexRiley, Ah, now rereading the question is confusing me also. I came by the question when googling "how to floor a Pandas series". So I'll leave this answer for others who reach the somewhat ambiguous question via the same route! – jpp Jan 14 '19 at 13:27
  • 1
    Yes, it'd be good to leave the answer - it could well be of use to people landing on this page via search-engines, as you say. – Alex Riley Jan 14 '19 at 13:30