2

I'm trying to use either locals() or *args to iterate over multiple function arguments. However, I am defining the function arguments as columns from a dataframe. How do I edit the following to have the float_format function iterate over a variable number of arguments?

#! /usr/bin/env python3

import pandas as pd

def float_format(a, b, c, d, e, f): #Change to single *args function argument?
        for x in range(len(data[a])):
                data[a][x] = data[a][x].replace(' Mbps', '')
        for x in range(len(data[b])):
                data[b][x] = data[b][x].replace(' Mbps', '')
        for x in range(len(data[c])):
                data[c][x] = data[c][x].replace(' Mbps', '')                
        for x in range(len(data[d])):
                data[d][x] = data[d][x].replace(' Mbps', '')
        for x in range(len(data[e])):
                data[e][x] = data[e][x].replace(' Mbps', '')
        for x in range(len(data[f])):
                data[f][x] = data[f][x].replace(' Mbps', '')

file = r'Original_File.xls'
data = pd.read_excel(file, header=[2])

float_format('Average Receive bps',
               'Peak Receive bps',
               'Received Bandwidth',
               'Average Transmit bps',
               'Peak Transmit bps',
               'Transmit Bandwidth')

data.to_excel('results.xlsx', 'w+')

So if I try

def float_format(*iterate):
        for arg in iterate:
            for x in range(len(data[iterate])):
                    data[iterate][x] = data[iterate][x].replace(' Mbps', '')

I'm getting traceback errors over the way the function runs.

example df

>>> data
            Display Name Interface Name  ... Peak Transmit bps Transmit Bandwidth
0       1951 - LAB - FW1          port1  ...         0.56 Mbps         10.00 Mbps
1       1951 - LAB - FW1          port1  ...         0.37 Mbps         10.00 Mbps
2       1951 - LAB - FW1          port1  ...         0.34 Mbps         10.00 Mbps
3       1951 - LAB - FW1          port1  ...         0.36 Mbps         10.00 Mbps
4       1951 - LAB - FW1          port1  ...         0.83 Mbps         10.00 Mbps
5       1951 - LAB - FW1          port1  ...         0.55 Mbps         10.00 Mbps
6       1951 - LAB - FW1          port1  ...         0.27 Mbps         10.00 Mbps
7       1951 - LAB - FW1          port1  ...         0.41 Mbps         10.00 Mbps
8       1951 - LAB - FW1          port2  ...         0.00 Mbps       1000.00 Mbps
9       1951 - LAB - FW1          port2  ...         0.00 Mbps       1000.00 Mbps
10      1951 - LAB - FW1          port2  ...         0.00 Mbps       1000.00 Mbps
11      1951 - LAB - FW1          port2  ...         0.00 Mbps       1000.00 Mbps
12      1951 - LAB - FW1          port2  ...         0.00 Mbps       1000.00 Mbps
13      1951 - LAB - FW1          port2  ...         0.00 Mbps       1000.00 Mbps
14      1951 - LAB - FW1          port2  ...         0.19 Mbps       1000.00 Mbps
15      1951 - LAB - FW1          port2  ...         0.31 Mbps       1000.00 Mbps
12
  • 1
    Can you clarify what you’re trying to do? Commented Feb 4, 2020 at 18:54
  • 1
    You can make a list and iterate over for i in [a,b,c,d,e,f]. Or if you want a variadic function, indeed use *args. Commented Feb 4, 2020 at 18:54
  • 2
    Exactly why don't you want to use *args? Commented Feb 4, 2020 at 18:54
  • 1
    Can you explain what the function is meant to do in the first place? It doesn't look very idiomatic. Commented Feb 4, 2020 at 19:40
  • 1
    @cgarrido What value? That sounds quite simple, why does the function look so complex? Can you take a step back, and provide some more context for the operation? Commented Feb 4, 2020 at 20:16

2 Answers 2

4

How about the following?

def test(*argv):
    for arg in argv:
            print(arg)

test('hello', 'world')
# hello
# world
Sign up to request clarification or add additional context in comments.

2 Comments

I tried something similar in my edit but I get a pretty lengthy traceback when trying to use *args.
Can you please post the traceback?
1

There's no need to use *args or anything like that here, we can take advantage of the operations provided by Pandas.


Setup code

import numpy as np
import pandas as pd

df_1 = pd.DataFrame(data={'col_1': np.random.randint(0, 10, 10),
                          'col_2': np.random.randint(0, 50, 10),
                          'col_3': np.random.randint(0, 5, 10)})

df_1[['col_1', 'col_3']] = df_1[['col_1', 'col_3']].astype(str) + ' Mbps'

print(df_1)
print(df_1.dtypes)

Output:

    col_1  col_2   col_3
0  1 Mbps     45  0 Mbps
1  2 Mbps     34  1 Mbps
2  6 Mbps     46  2 Mbps
3  7 Mbps      2  1 Mbps
4  6 Mbps     36  0 Mbps
5  9 Mbps     36  3 Mbps
6  4 Mbps     39  1 Mbps
7  4 Mbps     26  1 Mbps
8  1 Mbps     10  1 Mbps
9  6 Mbps      1  1 Mbps
col_1    object
col_2     int64
col_3    object
dtype: object

Method 1: Series.str.extract()

Using a loop

cols_to_change = ['col_1', 'col_3']

for col_name in cols_to_change:
    df_1[col_name] = df_1[col_name].str.extract(r"(\d+) Mbps", expand=False).astype(int)

Using DataFrame.apply()

cols_to_change = ['col_1', 'col_3']

df_1[cols_to_change] = df_1[cols_to_change].apply(lambda col: col.str.extract(r"(\d+) Mbps", expand=False)).astype(int)

Method 2: Series.str.slice()

Using a loop

cols_to_change = ['col_1', 'col_3']

for col_name in cols_to_change:
    df_1[col_name] = df_1[col_name].str.slice(stop=-5).astype(int)

Using DataFrame.apply()

cols_to_change = ['col_1', 'col_3']

df_1[cols_to_change] = df_1[cols_to_change].apply(lambda col: col.str.slice(stop=-5)).astype(int)

Result

DataFrame contents:

   col_1  col_2  col_3
0      9     40      3
1      4      8      3
2      6     49      4
3      4     38      4
4      6     25      4
5      3      8      3
6      3     27      3
7      0     45      1
8      7     24      4
9      3     29      2

dtypes:

col_1    int64
col_2    int64
col_3    int64
dtype: object

Let me know if you have any questions :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.