this is my first question here so please be patient with me.
My problem is as follows:
Assume we have a pandas Dataframe and we want to apply dynamically some pd.Series methods to a set of columns of this Dataframe. Why the following example doesn't work?
testframe=pd.DataFrame.from_dict({'col1': [1,2] ,'col2': [3,4] })
funcdict={'col1':[pd.Series.astype,str.replace],'col2':[pd.Series.astype,str.replace]}
argdict= {'col1':[['str'],['1','A']],'col2':[['str'],['3','B']]}
for col in testframe.columns:
for func in funcdict[col]:
idx=funcdict[col].index(func)
testframe[col]=testframe[col].func(*argdict[col][idx])
Expected outcome would be
col1 col2
0 'A' 'B'
1 '1' '4'
But instead i get
AttributeError: 'Series' object has no attribute 'func'
Remarkably
testframe['col1']=testframe['col1'].astype(*argdict['col1'][0])
works as expected, so somehow python seems to have a problem with the '.func' syntax despite the fact that
print(func)
yields the desired output: 'function NDFrame.astype at 0x00000186954EB840' etc.
Your syntax for calling a method is incorrect. There are 2 ways you can call a method in Python.
Direct
As you found, this will work. Note that astype
isn't referencing some other object, it's the actual name of the method belonging to pd.Series
.
testframe['col1'] = testframe['col1'].astype(*argdict['col1'][0])
Functional
The functional method demonstrates explicitly that astype
is the name of the method.
from operator import methodcaller
testframe['col1'] = methodcaller('astype', *argdict['col1'][0])(testframe[col])
Trying testframe[col].func(...)
will never work as func
is not the name of a pd.Series
method.