将功能应用于数据框的特定列

时间:2019-09-21 12:27:32

标签: python pandas function dataframe

def include_mean():
    if pd.isnull('Age'):
        if 'Pclass'==1:
            return 38
        elif 'Pclass'==2:
            return 30
        elif 'Pclass'==3:
            return 25
        else: return 'Age'

train['Age']=train[['Age','Pclass']].apply(include_mean(),axis=1)

为什么上面的代码给我一个类型错误。

 TypeError: ("'NoneType' object is not callable", 'occurred at index 0')

我现在知道正确的代码是

def impute_age(cols):
    Age = cols[0]
    Pclass = cols[1]

    if pd.isnull(Age):
if Pclass == 1:
            return 37
elif Pclass == 2:
            return 29
else:
            return 24
else:
        return Age

train['Age'] = train[['Age','Pclass']].apply(impute_age,axis=1)

现在我想知道为什么需要进行更改,即更改背后的确切原因。 “ cols”在这里做什么?

3 个答案:

答案 0 :(得分:1)

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html

在熊猫数据框上使用apply方法时,传递给应用的函数会在每一列(或每一行)上调用,具体取决于axis参数,该参数默认为{{1 }},列轴)。 因此,您的函数必须为0传递给该行的参数。

apply

这有一些问题。

  1. def include_mean(): if pd.isnull('Age'): if 'Pclass'==1: return 38 elif 'Pclass'==2: return 30 elif 'Pclass'==3: return 25 else: return 'Age' 保证为'Pclass'==1:,因为您要比较的是字符串(False和整数('Pclass'),它们不能相等。您想要的是比较一列1的值,您可以通过为该列建立索引来检索:Pclass,或者如果col["Pclass"]是第二个,则col[1]列。
  2. 如果Pclasspd.isnull('Age'),则函数返回False。由于字符串None不为null,因此应始终如此。当您执行'Age'时,您正在调用d.apply(include_mean()),它返回include_mean,然后将该值传递给None。但是apply需要一个可调用的对象(例如一个函数)。
  3. apply子句中,您将返回字符串else。这意味着您的数据框在某些单元格中的值为'Age'

您的第二个示例解决了这些问题:impute_age函数现在为row('Age')获取一个参数,对colsAge列的值进行查找和比较,并且您无需调用Pclass方法就可以传递该函数。

答案 1 :(得分:0)

欢迎使用Python。要回答您的问题,尤其是在开始阶段,有时您只需要打开一个新的IPython笔记本并尝试一下即可:

In [1]: import pandas as pd
   ...: def function(x):
   ...:     return x+1
   ...:
   ...: df = pd.DataFrame({'values':range(10)})
   ...: print(df)
   ...:
   values
0       0
1       1
2       2
3       3
4       4
5       5
6       6
7       7
8       8
9       9

In [2]: print(df.apply(function))
   values
0       1
1       2
2       3
3       4
4       5
5       6
6       7
7       8
8       9
9      10

在您的问题中,cols是您要遍历的每一行的值。

答案 2 :(得分:0)

Do not use apply(axis=1)。相反,您应该使用.loc在子集中设置值。这是针对大写字母的简单映射。

m = train.Age.isnull()
d = {1: 38, 2: 30, 3: 25}

train.loc[m, 'Age'] = train.loc[m, 'Pclass'].map(d)

对于最底下的情况,由于有else子句,我们可以使用np.select。这种工作方式是我们创建一个条件列表,该条件列表遵循if,elif else逻辑的顺序。然后,当遇到第一个True时,我们提供一个选择列表供您选择。由于您具有嵌套的逻辑,因此我们需要先对其进行嵌套,以便逻辑上将其读取为

if age is null and pclass == 1
elif age is null and pclass == 2
elif age is null 
else

样本数据

import pandas as pd
import numpy as np

df = pd.DataFrame({'Age': [50, 60, 70, np.NaN, np.NaN, np.NaN, np.NaN],
                   'Pclass': [1, 1, 1, 1, 2, np.NaN, 1]})
#    Age  Pclass
#0  50.0     1.0
#1  60.0     1.0
#2  70.0     1.0
#3   NaN     1.0
#4   NaN     2.0
#5   NaN     NaN
#6   NaN     1.0

m = df.Age.isnull()
conds = [m & df.Pclass.eq(1),
         m & df.Pclass.eq(2),
         m]
choices = [37, 29, 24]

df['Age'] = np.select(conds, choices, default=df.Age)
                                      # |
                                      # Takes care of else, i.e. Age not null
print(df)
#    Age  Pclass
#0  50.0     1.0
#1  60.0     1.0
#2  70.0     1.0
#3  37.0     1.0
#4  29.0     2.0
#5  24.0     NaN
#6  37.0     1.0