【问题标题】:Apply a lambda function to a dataframe with NaN values?将 lambda 函数应用于具有 NaN 值的数据帧?
【发布时间】:2020-09-05 15:47:35
【问题描述】:

我正在尝试执行在变量保持一致的行之间发生变化的计算。当一行有不完整的数据时,如何使用这个 lambda 函数?

跟进这个问题:Create a new column based on calculations that change between rows?

#example
import pandas as pd
import numpy as np

conversion = [["a",5],["b",1],["c",10]]
conversion_table = pd.DataFrame(conversion,columns=['Variable','Cost'])

data1 = [[1,"2*a+b"],[2,"c"],[3,"2*c"],[4, np.NaN]]
to_solve = pd.DataFrame(data1,columns=['Day','Q1'])

#Desired dataframe: 

desired = [[1,11],[2,10],[3,20]]
desired_table=pd.DataFrame(desired,columns=['Day','desired output'])

#Using lambda to map values does not work when NaN is present.

#Map values
mapping = dict(zip(conversion_table['Variable'], conversion_table['Cost']))

desired_table["solved"]=to_solve['Q1'].map(lambda x: eval(''.join([str(mapping[i]) if i.isalpha() else str(i) for i in x])))

当我的列不包含 NaN 值时,此代码有效,但当我的数据不完整时,我需要此代码。 我收到以下错误:'float' 对象不可迭代。 我只想将 NaN 值留在原处并填写其余部分。

【问题讨论】:

    标签: python pandas dataframe dictionary lambda


    【解决方案1】:
    desired_table["solved"]=to_solve['Q1'].map(lambda x: ..., na_action='ignore')
    

    应该做你想做的。

    In [6]: to_solve['Q1'].map(lambda x: eval(''.join([str(mapping[i]) if i.isalpha() else str(i) for i in x])), na_action='ignore')                                                                            
    Out[6]: 
    0    11.0
    1    10.0
    2    20.0
    3     NaN
    Name: Q1, dtype: float64
    

    【讨论】:

      【解决方案2】:

      您必须向.map 方法添加一个可选参数na_action='ignore',该方法传播NaN 值,而不将它们传递给映射对应关系

      用途:

      def solve(x):
          expr = ''.join(str(mapping[k]) if k in mapping else str(k) for k in x)
          return pd.eval(expr)
      
      desired_table["solved"]= to_solve['Q1'].map(solve, na_action='ignore')
      

      这导致desired_table 为:

         Day  desired output  solved
      0    1              11    11.0
      1    2              10    10.0
      2    3              20    20.0
      

      【讨论】:

      • 感谢您的解释和稍微重写。当我继续在许多列的其他函数中使用它时,帮助很大!
      【解决方案3】:

      您可以轻松过滤掉 NaN 值:

      desired_table["solved"]=to_solve.loc[~to_solve['Q1'].isna(),'Q1'].map(
            lambda x: eval(''.join([str(mapping[i]) if i.isalpha() else str(i) for i in x])))
      

      【讨论】:

        【解决方案4】:

        np.NaN 的类型为 float,因此当您尝试迭代它时(就像使用字符串时一样),您会得到 SyntaxError。为了避免这种情况,当您的数据中有 np.NaN 时,只需在 lambda 函数中定义一个默认值即可。

        def mappingFunc(x):
            return eval(''.join([str(mapping[i]) if i.isalpha() else str(i) for i in x])) if x is not np.NaN else np.NaN
        
        desired_table["solved"] = to_solve['Q1'].map(mappingFunc)
        

        【讨论】:

          猜你喜欢
          • 2022-10-01
          • 2021-08-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-13
          • 2017-01-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多