Home > Back-end >  Round any odd values to even values within specific columns in Python
Round any odd values to even values within specific columns in Python

Time:11-13

I have a dataset, df, where I would like to round any odd values to the next even values in columns in Python (except the number 1)

Data

site    a    b   c
bali    5    3   1
mali    7    19  1

Desired

site    a    b   c
bali    6    4   1
mali    8    20  1

Doing

setting this up, but I am stuck on how to point to the specific columns

if($num % 2 == 1) 

Any suggestion is appreciated

CodePudding user response:

In your case do

df.update(df.select_dtypes(np.number).applymap(lambda x : 1 if x==1 else x//2*2))
   a   b  c
0  4   2  1
1  6  18  1

CodePudding user response:

Set 'site' column as the index, using DataFrame.set_index so that the DataFrame only contains numeric columns. This can be generalised if you contain more non-numeric columns besides 'site'. Then, mask the numbers (nums) that are odd (nums % 2) and different from 1 (nums != 1), and add 1 to them, leaving the remaining unchanged. This can be done using DataFrame.mask. Finally, reset the index of the DataFrames so that 'site' is a column again.

# get all the non-numeric columns, like 'site', in the case you have multiple ones 
str_cols = df.select_dtypes(exclude='number').columns.tolist()

df = (
    df.set_index(str_cols)    # set the non-numeric column(s) as index 
      .mask(lambda nums: (nums % 2 == 1) & (nums != 1),  # add 1 to every odd number !=1 
            lambda nums: nums   1)                  # and leave the remaining unchanched 
      .reset_index()  # restore the non-numeric column(s) 
)

>>> df

   site  a   b  c
0  bali  6   4  1
1  mali  8  20  1


Actually, setting and resetting the index can be avoided. Here is a simpler version of the above solution

# get all the numeric columns 
num_cols = df.select_dtypes(include='number').columns.tolist()

# update only the numeric columns with the same logic 
df[num_cols] = df[num_cols].mask(lambda nums: (nums % 2 == 1) & (nums != 1),
                                 lambda nums: nums   1)

CodePudding user response:

use simple numpy to exclude 1

import numpy as np
data = np.array([
    [5, 3, 1],
    [7, 19,1]
])

data = data   (data%2 * np.where(data==1, 0, 1))

print(data)

# array([[ 6,  4,  1],
#        [ 8, 20,  1]])
  • Related