pythonpandasdataframeapplyrounding

Change the decimal value of each value in each column to 0.5 while maintaining the same leading integer python pandas


CONTEXT

I am NOT trying to round to the nearest 0.5. I know there are questions on here that address that. Rather, I am trying to change the decimal value of each value in each row to 0.5 while maintaining the same leading integer. For example, I have df:

df = pd.DataFrame({'foo':[1.5,5.5,7.11116],'bar':[3.66666661, 10.5, 4.5],'baz':[8.5,3.111118,2.5]},index=['a','b','c'])

df


      foo     bar          baz
a   1.50000 3.666667    8.500000
b   5.50000 10.500000   3.111118
c   7.11116 4.500000    2.500000

INTENDED OUTPUT

I would like each cell to end in 0.5. As you can see, there are some erroneous values. Here is my intended output:

      foo     bar       baz
a   1.5       3.5       8.5
b   5.5       10.5      3.5
c   7.5       4.5       2.5

WHAT I HAVE TRIED

At first I thought I could maybe iterate through the columns in a list comprehension, but then figured a combination of where() and apply(), or maybe just apply() with a lambda function might be more readable:

df = df.where(df % 0.5 == 0, 'fix this')
df

    foo          bar        baz
a   1.5       fix this      8.5
b   5.5        10.5       fix this
c   fix this    4.5         2.5

Where I am stumped is trying to create a function that changes the decimal value to .5 rather than rounding to the nearest 0.5 (which, for example, in this case, round 3.111118 to 3.0 when I want 3.5).


Solution

  • You can floor (or convert to int with astype), then add 0.5:

    import numpy as np
    
    out = np.floor(df).add(0.5)
    

    Or:

    out = df.astype(int).add(0.5)
    

    Output:

       foo   bar  baz
    a  1.5   3.5  8.5
    b  5.5  10.5  3.5
    c  7.5   4.5  2.5
    

    NB. a quick test suggests that floor is about 30% faster.