【问题标题】:"Function" & a "for" logic in pandaspandas 中的“函数”和“for”逻辑
【发布时间】:2015-05-15 16:00:50
【问题描述】:

我有一个通过参数字典传递的输入参数,如下所示 -

paramDict = {  "Period":
                    {
                    "Description": "A Period",
                    "Value" : ['9']
                    },
               "AdditionalPeriods":
                        {
                        "Description": "An AdditionalPeriod",
                        "Value" : ['1']
                        }
            }

而且,我有一个数据框“df_AssetCst”,如下所示 -

>>> df_AssetCst.dtypes
FLCO                object
FLN01               object
FLN02               object
FLN03               object
FLN04               object
FLN05               object
FLN06               object
FLN07               object
FLN08               object
FLN09               object
FLN10               object
FLN11               object
FLN12               object
FLN13               object
FLN14               object

现在基于传递给参数字典的值,我想在python pandas中实现下面的“if-else”条件-

def func(row):
    if pd.Series(paramDict['AdditionalPeriods']['Value'][0]) == '0':
        return '0'        
    elif pd.Series(paramDict['AdditionalPeriods']['Value'][0]) == '1':
        return df_AssetCst['FLN13']   
    elif pd.Series(paramDict['AdditionalPeriods']['Value'][0]) == '2':
        return (df_AssetCst['FLN13'].astype(int)
              + df_AssetCst['FLN14'].astype(int)) 
    else:
        return 'other'  

在sql中,上面的case逻辑如下-

Case AdditionalPeriods = 0, Then NewColumn = 0
Case AdditionalPeriods = 1, Then NewColumn = FLN013
Case AdditionalPeriods = 2, Then NewColumn = FLN013 + FLN014

现在,我想使用该函数在数据框中创建一个新列 -

df_AssetCst['NewColumn'] = df_AssetCst.apply(func, axis=1)

但是,这给了我以下错误-

ValueError: ('The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().', u'occurred at index 0')

在这之后,我想实现下面的“For”逻辑-

if Period.value = '9'
then NewColumn2 =  FLN01+FLN02+FLN03+FLN04+FLN05+FLN06+FLN07+FLN08+FLN09 

你能帮我一些方向和实现相同目标的最佳方法吗?谢谢

********** 我的解决方案 ***********

#1. Function logic :
def func(row):   
    if paramDict['AdditionalPeriods']['Value'][0] == '0':
        var = 0       
    elif paramDict['AdditionalPeriods']['Value'][0] == '1':
        var = int(row['FLN13'])   
    elif paramDict['AdditionalPeriods']['Value'][0] == '2':
        var = int(row['FLN13']) + int(row['FLN14'])                                 
    else:
        var = -1

    return(var) 

#2. For logic
In_Period = paramDict['Period']['Value'][0]
colList = ['FLN{:0>2}'.format(X) for X in range(1, In_Period + 1)]
df_AssetCst['NewColumn1'] = df_AssetCst[colList].astype(int).sum(axis=1)

【问题讨论】:

  • ValueError: ('The truth value of a Series is ambiguous. ... 在测试 np.ndarray 和标量之间的条件时发生。用np.all()np.any() 包裹整个条件。实际上,pd.Series 可能在func 中被滥用。需要更多信息,但我认为apply() 使用不正确,因为row 参数pd.Series 从未在func() 中使用。来自pandas“传递给函数的对象是具有 DataFrame 索引 (axis=0) 或列 (axis=1) 索引的 Series 对象。”
  • @MarkMikofski - 添加了上面对我有用的解决方案。谢谢。

标签: python python-2.7 python-3.x pandas


【解决方案1】:

使用您在更新的答案(即您的解决方案)中编写的func 函数,您应该能够使用带有参数axis=1DataFrame.apply 方法。 (我没有测试过,但也许你可以尝试应用它并报告错误信息,如果有的话)

但是,在这个函数中,你在全局范围内引用了param_dict,虽然它有效,但如果你不小心,可能会导致意想不到的后果,而且 IMO 以后可能会导致更多的头痛。

这是func 函数的另一个版本。这个参数将一行 pd.Series 类型和一个 param_dict(您在问题中提供的字典)作为参数

def func(row, param_dict):
   """
   Gets the key from the param_dict, and tries to return the element
   from _conversion_map.
   if the key doesn't exist in the conversion map, then returns -1
   """
   key = param_dict['AdditionalPeriods']['Value'][0] 
   _conversion_map = {
        '0': 0,
        '1': int(row.FLN13),
        '2': int(row.FLN13) + int(row.FLN14)
        }
    try:
        return _conversion_map[key]
    except KeyError:
        return -1

那么这应该可以工作:

df_AssetCst['NewColumn'] = df_AssetCst.apply(func, axis=1, param_dict=param_dict)

这个答案的关键是apply 方法接受任意位置和关键字参数并将它们传递给函数。

【讨论】:

    猜你喜欢
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 2018-11-13
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2016-10-30
    • 1970-01-01
    相关资源
    最近更新 更多