Apply a method from a list of methods to pandas dataframe
这是我第一个问题,请耐心等待。
我的问题是:
假设我们有一个pandas数据帧,并且我们想要动态地将一些pd.series方法应用到这个数据帧的一组列中。为什么下面的例子不起作用?
1 2 3 4 5 6 7 8 | 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]) |
预期结果是
1 2 3 | col1 col2 0 'A' 'B' 1 '1' '4' |
但是我得到了
1 | AttributeError: 'Series' object has no attribute 'func' |
显著地
1 | testframe['col1']=testframe['col1'].astype(*argdict['col1'][0]) |
按预期工作,所以尽管事实上
生成所需的输出:"function ndframe.astype at 0x00000186954eb840"等。
您可以使用
1 2 3 4 5 6 7 | In [74]: s = pd.Series(['1','2']) In [75]: rgetattr(s, 'str.replace')('1', 'A') Out[75]: 0 A 1 2 dtype: object |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import functools import pandas as pd def rgetattr(obj, attr, *args): def _getattr(obj, attr): return getattr(obj, attr, *args) return functools.reduce(_getattr, [obj] + attr.split('.')) testframe = pd.DataFrame.from_dict({'col1': [1, 2], 'col2': [3, 4]}) funcdict = {'col1': ['astype', 'str.replace'], 'col2': ['astype', 'str.replace']} argdict = {'col1': [['str'], ['1', 'A']], 'col2': [['str'], ['3', 'B']]} for col in testframe.columns: for attr, args in zip(funcdict[col], argdict[col]): testframe[col] = rgetattr(testframe[col], attr)(*args) print(testframe) |
产量
1 2 3 | col1 col2 0 A B 1 2 4 |
1 2 3 4 5 | In [92]: s = pd.Series(['1','2']); s Out[92]: 0 1 1 2 dtype: object |
我们可以使用
1 2 3 4 | In [85]: getattr(s, 'str') Out[85]: <pandas.core.strings.StringMethods at 0x7f334a847208> In [91]: s.str == getattr(s, 'str') Out[91]: True |
要获得
1 2 3 4 5 | In [88]: getattr(getattr(s, 'str'), 'replace') Out[88]: <bound method StringMethods.replace of <pandas.core.strings.StringMethods object at 0x7f334a847208>> In [90]: s.str.replace == getattr(getattr(s, 'str'), 'replace') Out[90]: True |
但是,如果我们指定
1 2 | funcdict = {'col1': ['astype', 'str.replace'], 'col2': ['astype', 'str.replace']} |
然后,我们需要某种方式来处理需要一次呼叫
为了将这两种情况统一为一种简单的语法,我们可以使用
递归由
调用方法的语法不正确。在Python中有两种方法可以调用方法。
直接的
正如你所发现的,这是可行的。注意,
1 | testframe['col1'] = testframe['col1'].astype(*argdict['col1'][0]) |
功能性
函数方法显式地证明
1 2 3 | from operator import methodcaller testframe['col1'] = methodcaller('astype', *argdict['col1'][0])(testframe[col]) |
尝试