Python используя функцию apply, чтобы пропустить Nan - PullRequest
0 голосов
/ 28 января 2020

Я пытаюсь предварительно обработать набор данных для использования в XGBoost, сопоставив классы в каждом столбце с числовыми значениями. Рабочий пример выглядит следующим образом:

from collections import defaultdict
from sklearn.preprocessing import LabelEncoder
import pandas as pd

df1 = pd.DataFrame(data = {'col1': ['A', 'B','C','B','A'], 'col2': ['Z', 'X','Z','Z','Y'], 'col3':['I','J','I','J','J']})
d = defaultdict(LabelEncoder)
encodedDF = df1.apply(lambda x: d[x.name].fit_transform(x))
inv = encodedDF.apply(lambda x: d[x.name].inverse_transform(x))

Где encodedDF выдает результат:

col1 col2 col3
 0    2    0
 1    0    1
 2    2    0
 1    2    1
 0    1    1

И inv просто возвращает его обратно в исходный кадр данных. Моя проблема в том, что когда вводятся нулевые значения:

df2 = pd.DataFrame(data = {'col1': ['A', 'B',None,'B','A'], 'col2': ['Z', 'X','Z',None,'Y'], 'col3':['I','J','I','J','J']})
encodedDF = df2.apply(lambda x: d[x.name].fit_transform(x))

Выполнение выше приведёт к ошибке:

"TypeError: ('аргумент должен быть строкой или числом', 'произошел в индексе col1 ') "

По сути, я хочу применить кодировку, но пропустите значения отдельных ячеек, которые являются нулевыми, чтобы получить такой вывод:

col1 col2 col3
0     2    0
1     0    1
NaN   2    0
1     NaN  1
0     1    1

Я не могу использовать dropna () перед применением кодировки, потому что тогда я теряю данные, которые буду пытаться вписать в XBSoost. Я не могу использовать условные выражения для пропуска x, если он нулевой (например, с помощью x.notnull () в лямбда-функции), потому что fit_transform (x) использует объект Pandas .Series в качестве аргумента и ни один из логических операторов, которые я можно использовать в условном виде, чтобы делать то, что я пытаюсь сделать. Я не уверен, что еще можно попробовать, чтобы заставить это работать. Я надеюсь, что то, что я пытаюсь сделать, имеет смысл. Дайте мне знать, если мне нужно уточнить.

1 Ответ

0 голосов
/ 29 января 2020

Кажется, я нашел обходной путь. Вероятно, мне следовало использовать класс OneHotEncoder от sklearn с самого начала вместо комбинации LabelEncoder / defaultdict. Я новичок во всем этом. Я заменил NaN на фиктивные значения, а затем отбросил эти фиктивные значения после кодирования кадра данных.

import pandas as pd
from sklearn.preprocessing import OneHotEncoder

df = pd.DataFrame(data = {'col1': ['A', 'B','C',None,'A'], 'col2': ['Z', 'X',None,'Z','Y'], 'col3':['I','J',None,'J','J'], 'col4':[45,67,None,32,94]})

replaceVals = {'col1':'missing','col2':'missing','col3':'missing','col4':-1}
df = df.fillna(value = replaceVals,axis=0)

drop = [['missing'],['missing'],['missing'],[-1]]
enc = OneHotEncoder(drop=drop)
encodeDF = enc.fit_transform(df)
...