Search code examples
pythonpandasdataframepandas-apply

How to make decimal part rounding filter, using python pandas Dataframe apply method


I want to make decimal filter with pandas Dataframe.
Filter will ceiling and flooring their decimal part.

Like this
threshold is 0.3 and 0.7
0.75 -> 1
1.99 -> 2
9.13 -> 9
326.2 -> 326
34.5 -> 34.5
68.4 -> 68.4

import pandas as pd

def threshold_function(df):
    print(df)
    decimal_part = df - np.floor(df)
    if (decimal_part <= 0.3):
        return np.floor(df)
    elif (0.7 <= decimal_part):
        return np.floor(df) + 1
    return df

example = pd.DataFrame([0.75,1.99,9.13,326.2,34.5])
filtered_df = example.apply(threshold_function)

I don't know why data frame apply method didn't work.

The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Thank you :)


Solution

  • An option with np.modf + np.select:

    decimal, base = np.modf(example)
    filtered_df = pd.DataFrame(np.select(
        [decimal <= 0.3, decimal >= 0.7],
        [base, base + 1],
        default=example
    ), columns=example.columns, index=example.index)
    

    Example:

    example = pd.DataFrame([[0.75, 1.99, 9.13, 326.2, 34.5],
                            [0.85, 2.65, 10.19, 42.2, 61.65]])
    
          0     1      2      3      4
    0  0.75  1.99   9.13  326.2  34.50
    1  0.85  2.65  10.19   42.2  61.65
    

    filtered_df:

         0     1     2      3      4
    0  1.0  2.00   9.0  326.0  34.50
    1  1.0  2.65  10.0   42.0  61.65
    

    Or a revision via applymap:

    def threshold_function(v):
        decimal_part = v - np.floor(v)
        if decimal_part <= 0.3:
            return np.floor(v)
        elif 0.7 <= decimal_part:
            return np.ceil(v)
        return v
    
    
    example = pd.DataFrame([[0.75, 1.99, 9.13, 326.2, 34.5],
                            [0.85, 2.65, 10.19, 42.2, 61.65]])
    filtered_df = example.applymap(threshold_function)
    

    example

          0     1      2      3      4
    0  0.75  1.99   9.13  326.2  34.50
    1  0.85  2.65  10.19   42.2  61.65
    

    filtered_df:

         0     1     2      3      4
    0  1.0  2.00   9.0  326.0  34.50
    1  1.0  2.65  10.0   42.0  61.65