pythonroundingsplat

Python Creating a function with unkown number arguments with splat operator


I am am trying to round numbers in a dataframe that has lists as values for each row. I need whole numbers to have no decimal and floats to only have two places after the decimal. There is an unknown number of values for each list (some lists have 2 values, some have 4 or 5 or more). Here is what I have:

df = pd.DataFrame({"A": [[16.0, 24.4175], [14.9687, 16.06], [22.75, 23.00]]})

def remove_exponent(num):
    return num.to_integral() if num == num.to_integral() else num.normalize()

def round_string_float(x):
    try:
        return remove_exponent(Decimal(x).quantize(TWOPLACES))
    except:
        return x  
df['A']=df['A'].apply(lambda x: [round_string_float(num) for num in x])
But this gives me: [Decimal('16'), Decimal('24.42')]

Here is what I am trying:

def round(num):
     if str(numbers).find('/') > -1:
          nom, den = numbers.split(',')
          number=round_string_float(nom)
          second=round_string_float(den)
          return f'[{number}, {second}]'
but there has to be an easier way to do this

Here is what I want:

df = pd.DataFrame({"A": [[16, 24.42], [14.97, 16.06], [22.75, 23]]})

I would like to know have to use **args to do this but really anything that works would be good


Solution

  • I created an answer to this question that goes above and beyond what I wanted but I think it will help anyone looking for something similar. The problem with my company is we have to upload lists as values in a dataframe to the database. This is why the code is so ad-hoc:

    from decimal import *
    TWOPLACES = Decimal(10) ** -2
    from natsort import natsorted
    import ast
    from fractions import Fraction
    #----------------------------------------------------------------
    # remove_exponent and round string float are designed to round whole numbers 16.00 to 16, and rounds numbers with 3 or more decimals to 2 decimals 16.254 to 16.25
    def remove_exponent(num): 
        return num.to_integral() if num == num.to_integral() else num.normalize()
    
    def round_string_float(x):
        try:
            return remove_exponent(Decimal(x).quantize(TWOPLACES))
        except:
            return x 
    #------------------------------------------------------------------------------
    # frac2string converts fractions to decimals: 1 1/2 to 1.5
    def frac2string(s):
        i, f = s.groups(0)
        f = round_string_float(Fraction(f))
        return str(int(i) + round_string_float(float(f)))
    
    #------------------------------------------
    #remove duplicates is self explanitory
    def remove_duplicates(A):
        [A.pop(count) for count,elem in enumerate(A) if A.count(elem)!=1]
        return A
    
    
    # converts fractions and rounds numbers
    df['matches'] = df['matches'].apply(lambda x:[re.sub(r'(?:(\d+)[-\s])?(\d+/\d+)', frac2string, x)])
    
    # removes duplicates( this needs to be in the format ["\d","\d"]
    df['matches'] = df['matches'].apply(lambda x: remove_duplicates([n.strip() for n in ast.literal_eval(x)]))