Применить функцию к определенному столбцу данных - PullRequest
0 голосов
/ 21 сентября 2019
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)

Теперь я хочу знать, почемутребуемые изменения, т.е. точные причины их возникновения.Что здесь делают «колы»?

Ответы [ 3 ]

1 голос
/ 21 сентября 2019

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

Когда вы используете метод apply на фрейме данных panda, функция, которую вы передаете для применения, вызывается для каждого столбца (или строки, в зависимости от параметра axis, которыйпо умолчанию 0 (ось столбца).Таким образом, ваша функция должна иметь параметр для строки, который apply передаст ей.

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'

Есть несколько проблем с этим.

  1. 'Pclass'==1: гарантированно будет False, поскольку вы сравниваете строку ('Pclass') и целое число (1), которые не могут быть равны.Вам нужно сравнить значение записи Pclass столбца, которую можно получить, проиндексировав столбец: col["Pclass"] или col[1], если Pclass - второй столбец.
  2. если pd.isnull('Age') равно False, функция возвращает None.Поскольку строка 'Age' не равна нулю, это всегда должно иметь место.Когда вы делаете d.apply(include_mean()), вы звоните include_mean, который возвращает None, а затем передаете это значение apply.Но apply ожидает вызова (например, функция).
  3. В предложении else вы возвращаете строку 'Age'.Это означает, что ваш фрейм данных имел бы значение 'Age' в некоторых ячейках.

Ваш второй пример устраняет эти проблемы: функция impute_age теперь принимает параметры для строки (cols), значениестолбцы Age и Pclass ищутся и сравниваются, и вы передаете эту функцию, не вызывая ее, в метод apply.

0 голосов
/ 21 сентября 2019

Не использовать 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
0 голосов
/ 21 сентября 2019

Добро пожаловать в 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 - это значение для каждой строки, которую выЗацикливаемся.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...