我有一个以下dataFrame
mn = pd.DataFrame({'fld1': [2.23, 4.45, 7.87, 9.02, 8.85, 3.32, 5.55],'fld2': [125000, 350000,700000, 800000, 200000, 600000, 500000],'lType': ['typ1','typ2','typ3','typ1','typ3','typ1','typ2'], 'counter': [100,200,300,400,500,600,700]})
Run Code Online (Sandbox Code Playgroud)
映射功能
def getTag(rangeAttribute):
sliceDef = {'tag1': [1, 4], 'tag2': [4, 6], 'tag3': [6, 9],
'tag4': [9, 99]}
for sl in sliceDef.keys():
bounds = sliceDef[sl]
if ((float(rangeAttribute) >= float(bounds[0]))
and (float(rangeAttribute) <= float(bounds[1]))):
return sl
def getTag1(rangeAttribute):
sliceDef = {'100-150': [100000, 150000],
'150-650': [150000, 650000],
'650-5M': [650000, 5000000]}
for sl in sliceDef.keys():
bounds = sliceDef[sl]
if ((float(rangeAttribute) >= float(bounds[0]))
and (float(rangeAttribute) <= float(bounds[1]))):
return sl
Run Code Online (Sandbox Code Playgroud)
我想根据fld1和fld2的标签计算总和.目前,我必须为不同类型的字段编写具有硬编码值的不同函数.MAP函数只需要1个参数.除MAP之外是否还有其他函数
也可以将sliceDef作为输入参数.
mn.groupby([mn['fld1'].map(getTag),mn['fld2'].map(getTag1),'lType'] ).sum()
Run Code Online (Sandbox Code Playgroud)
您可以使用pd.cut而不是使用map (感谢DSM和Jeff指出这一点):
import numpy as np
import pandas as pd
mn = pd.DataFrame(
{'fld1': [2.23, 4.45, 7.87, 9.02, 8.85, 3.32, 5.55],
'fld2': [125000, 350000, 700000, 800000, 200000, 600000, 500000],
'lType': ['typ1', 'typ2', 'typ3', 'typ1', 'typ3', 'typ1', 'typ2'],
'counter': [100, 200, 300, 400, 500, 600, 700]})
result = mn.groupby(
[pd.cut(mn['fld1'], [1,4,6,9,99], labels=['tag1', 'tag2', 'tag3', 'tag4']),
pd.cut(mn['fld2'], [100000, 150000, 650000, 5000000],
labels=['100-150', '150-650', '650-5M']),
'lType']).sum()
print(result)
Run Code Online (Sandbox Code Playgroud)
产量
counter fld1 fld2
lType
tag1 100-150 typ1 100 2.23 125000
150-650 typ1 600 3.32 600000
tag2 150-650 typ2 900 10.00 850000
tag3 150-650 typ3 500 8.85 200000
650-5M typ3 300 7.87 700000
tag4 650-5M typ1 400 9.02 800000
Run Code Online (Sandbox Code Playgroud)
这比调用更快,getTag或者getTag1 对系列中的每个值都更快.相反,pd.cut使用np.searchsorted只返回一次调用返回所有索引(此外,searchsorted使用用C编写的O(log n)二进制搜索而不是用Python编写的O(n)循环).
一个微妙的要点:返回的密钥sliceDef.keys()不保证按任何特定顺序排列.它甚至可以在运行之间改变(至少在Python3中).您的标准使用完全封闭的间隔:
if ((float(rangeAttribute) >= float(bounds[0]))
and (float(rangeAttribute) <= float(bounds[1]))):
Run Code Online (Sandbox Code Playgroud)
因此,如果rangeAttribute碰巧落入其中一个值,那么首先测试哪个键可能很重要bounds.
所以你当前的代码是不确定的.
pd.cut 使用半开间隔,因此每个值将分为一个且只有一个类别,从而避免了问题.
并回答一般问题:是的,有一种方法可以传递额外的参数 - 使用apply而不是map(感谢Andy Hayden指出这一点):
import numpy as np
import pandas as pd
def getTag(rangeAttribute, sliceDef):
for sl in sliceDef.keys():
bounds = sliceDef[sl]
if ((float(rangeAttribute) >= float(bounds[0]))
and (float(rangeAttribute) <= float(bounds[1]))):
return sl
sliceDef = {'tag1': [1, 4], 'tag2': [4, 6], 'tag3': [6, 9],
'tag4': [9, 99]}
sliceDef1 = {'100-150': [100000, 150000],
'150-650': [150000, 650000],
'650-5M': [650000, 5000000]}
mn = pd.DataFrame(
{'fld1': [2.23, 4.45, 7.87, 9.02, 8.85, 3.32, 5.55],
'fld2': [125000, 350000, 700000, 800000, 200000, 600000, 500000],
'lType': ['typ1', 'typ2', 'typ3', 'typ1', 'typ3', 'typ1', 'typ2'],
'counter': [100, 200, 300, 400, 500, 600, 700]})
result = mn.groupby([mn['fld1'].apply(getTag, args=(sliceDef, ))
,mn['fld2'].apply(getTag, args=(sliceDef1, )),
'lType'] ).sum()
print(result)
Run Code Online (Sandbox Code Playgroud)
尽管如此,我不建议使用apply这个特定的问题,因为pd.cut它更快,更容易使用,并避免了dict键问题的非确定性顺序.但是知道apply可以采取额外的位置参数可能会在将来帮助你.
| 归档时间: |
|
| 查看次数: |
1613 次 |
| 最近记录: |