Rona
Rona

Reputation: 97

modifying global variable pass in parameter function in place on python

i thought i understood the global vs local scope for variable but i am struggling on a case.

Here the function i want to implement:

def login_table(id_name_verified, id_password):
    """
    :param id_name_verified: (DataFrame) DataFrame with columns: Id, Login, Verified.
    :param id_password: (numpy.array) Two-dimensional NumPy array where each element
                        is an array that contains: Id and Password
    :returns: (None) The function should modify id_name_verified DataFrame in-place.
              It should not return anything.
     Goal : in id_name_verified, 'Verified' column should be removed and password should be added from id_password with corresponding id and the column be named password
    """


Test:
import pandas as pd
import numpy as np


def login_table(id_name_verified, id_password):
    id_name_verified.drop(columns="Verified",inplace=True)
    password = pd.DataFrame(id_password)
    password.columns = ["Id", "Password"]
    id_name_verified =id_name_verified.merge(password, on=['Id'])




id_name_verified = pd.DataFrame([[1, "JohnDoe", True], [2, "AnnFranklin", False]], columns=["Id", "Login", "Verified"])
id_password = np.array([[1, 987340123], [2, 187031122]], np.int32)
login_table(id_name_verified, id_password)
print(id_name_verified)


Expected Output:

   Id        Login   Password
0   1      JohnDoe  987340123
1   2  AnnFranklin  187031122

Output i got:

   Id        Login
0   1      JohnDoe
1   2  AnnFranklin

When I run this on pycharm, i see the problem is in the last line of my function where id_name_verified is identified as being from outer scope. This inspection detects shadowing names defined in outer scopes.

If i don't define a function it will work so I guess there is something I miss in the understanding of parameters pass to a function; any suggestions ?

Upvotes: 2

Views: 1984

Answers (5)

Tokay
Tokay

Reputation: 11

For faster version use mapping. Creating new DataFrame is slow and costly way.

import pandas as pd
import numpy as np

def login_table(id_name_verified, id_password):
    """
    :param id_name_verified: (DataFrame) DataFrame with columns: Id, Login, Verified.   
    :param id_password: (numpy.array) Two-dimensional NumPy array where each element
                        is an array that contains: Id and Password
    :returns: (None) The function should modify id_name_verified DataFrame in-place. 
              It should not return anything.
    """   
    id_name_verified.drop(columns='Verified', inplace=True)
    mapping = {li[0]: li[1] for li in id_password}
    id_name_verified['Password'] = id_name_verified['Id'].map(mapping)

id_name_verified = pd.DataFrame([[1, "JohnDoe", True], [2, "AnnFranklin", False]], columns=["Id", "Login", "Verified"])
id_password = np.array([[1, 987340123], [2, 187031122]], np.int32)
login_table(id_name_verified, id_password)
print(id_name_verified)

Upvotes: 1

RamWill
RamWill

Reputation: 318

import pandas as pd
import numpy as np

def login_table(id_name_verified, id_password):
    id_name_verified.drop(inplace=True, columns="Verified") # drop verified column inplace
    id_name_verified.insert(loc=2,column="Password",value=np.nan) # insert password column inplace
    for row in range(len(id_password)): 
        # apply the password on the rows that match using at
        id = id_password[row][0]
        pw = id_password[row][1]
        id_name_verified.at[row, "Password"] = pw

id_name_verified = pd.DataFrame([[1, "JohnDoe", True], [2, "AnnFranklin", False]], columns=["Id", "Login", "Verified"])
id_password = np.array([[1, 987340123], [2, 187031122]], np.int32)
login_table(id_name_verified, id_password)
print(id_name_verified)

Upvotes: 1

Abbos-Ali Mirkhanov
Abbos-Ali Mirkhanov

Reputation: 1

import pandas as pd
import numpy as np 

def login_table(id_name_verified, id_password):
    # in place makes sure that changes are made in a current dataframe 
    id_name_verified.drop('Verified', 1, inplace= True) 
    # id_password[:,1] -> : selects all rows and 1 selects only second column
    id_name_verified['Password'] = id_password[:,1]
    pass


id_name_verified = pd.DataFrame([[1, "JohnDoe", True], [2, "AnnFranklin", False]], columns=["Id", "Login", "Verified"])
id_password = np.array([[1, 987340123], [2, 187031122]], np.int32)
login_table(id_name_verified, id_password)
print(id_name_verified)


Upvotes: 0

python_enthusiast
python_enthusiast

Reputation: 31

Here's the code that passes all 4 tests on TestDome:

import pandas as pd
import numpy as np

def login_table(id_name_verified, id_password):
    """
    :param id_name_verified: (DataFrame) DataFrame with columns: Id, Login, Verified.   
    :param id_password: (numpy.array) Two-dimensional NumPy array where each element
                        is an array that contains: Id and Password
    :returns: (None) The function should modify id_name_verified DataFrame in-place. 
              It should not return anything.
    """   
    id_name_verified.drop(columns = 'Verified', inplace = True)
    password_df = pd.DataFrame(id_password)
    pass_col = password_df[1]
    id_name_verified['Password'] = pass_col

id_name_verified = pd.DataFrame([[1, "JohnDoe", True], [2, "AnnFranklin", False]], columns=["Id", "Login", "Verified"])
id_password = np.array([[1, 987340123], [2, 187031122]], np.int32)
login_table(id_name_verified, id_password)
print(id_name_verified)

You drop the 'Verified' column, then create a new data frame just out of id_password, take the column that contains passwords and add it to the id_name_verified data frame.

Upvotes: 0

Sushanth
Sushanth

Reputation: 2342

Here is the code that will solve your problem:

import pandas as pd
import numpy as np

def login_table( id_password):
    global id_name_verified
    id_name_verified.drop(columns="Verified",inplace=True)
    password = pd.DataFrame(id_password)
    password.columns = ["Id", "Password"]
    id_name_verified =id_name_verified.merge(password, on=['Id'])

id_name_verified = pd.DataFrame([[1, "JohnDoe", True], [2, "AnnFranklin", False]], columns=["Id", "Login", "Verified"])
id_password = np.array([[1, 987340123], [2, 187031122]], np.int32)
login_table( id_password)
print(id_name_verified)

The changes I made are, I declared the "id_name_verified" as global inside the function "login_table". Once this is done you don't have to pass "id_name_verified" again to the function because by using the keyword "global" we have already given access of "id_name_verified" to the function "login_table". So removed the "id_name_verified" as one of the arguments to the function.

Upvotes: 1

Related Questions