Fuction не может интерпретировать нан значение - PullRequest
0 голосов
/ 18 декабря 2018

Я пытаюсь избавиться от значений NaN в кадре данных.Вместо того, чтобы заполнять NaN средними значениями или выполнять ffill, я хотел заполнить пропущенные значения в соответствии с распределением значений внутри столбца.Другими словами, если в столбце 120 строк, 20 - NaN, 80 - 1,0, а 20 - 0,0, я хочу заполнить 80% значений NaN значением 1. Обратите внимание, что столбец содержит числа с плавающей запятой.

Я сделал для этого функцию:

def fill_cr_hist(x):
    if x is pd.np.nan:
        r = random.random()
        if r > 0.80:
            return 0.0
        else:
            return 1.0
    else:
        return x

Однако, когда я вызываю функцию, она не изменяет значения NaN.

df['Credit_History'] = df['Credit_History'].apply(fill_cr_hist)

Я заполнял значения NaN с помощью pd.np.nan., но это ничего не изменило.

df['Credit_History'].fillna(value=pd.np.nan, inplace=True)
df['Credit_History'] = df['Credit_History'].apply(fill_cr_hist)

Другая функция, которую я написал, практически идентична и работает нормально.В этом случае столбец содержит строки.

def fill_self_emp(x):
    if x is pd.np.nan:
        r = random.random()
        if r > 0.892442:
            return 'Yes'
        else:
            return 'No'
    else:
        return x

1 Ответ

0 голосов
/ 18 декабря 2018
ser = pd.Series([
    1, 1, np.nan, 0, 0, 1, np.nan, 1, 1, np.nan, 0, 0, np.nan])

Используйте value_counts с normalize=True, чтобы получить список вероятностей, соответствующих вашим значениям.Затем генерируйте значения случайным образом в соответствии с заданным распределением вероятностей и используйте fillna для заполнения NaN.

p = ser.value_counts(normalize=True).sort_index().tolist()   
u = np.sort(ser.dropna().unique())
ser = ser.fillna(pd.Series(np.random.choice(u, len(ser), p=p)))

Это решение должно работать для любого числа числовых / категориальных значений, а не только для 0и 1с.Если данные являются строковым типом, используйте pd.factorize и преобразуйте в числовое значение.


Подробности

Сначала вычислите распределение вероятностей:

ser.value_counts(normalize=True).sort_index()

0.0    0.444444
1.0    0.555556
dtype: float64

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

np.sort(ser.dropna().unique())
array([0., 1.])

Наконец, сгенерируйте случайные значения с заданным распределением вероятности.

pd.Series(np.random.choice(u, len(ser), p=p))

0     0.0
1     0.0
2     1.0
3     0.0
4     0.0
5     0.0
6     1.0
7     1.0
8     0.0
9     0.0
10    1.0
11    0.0
12    1.0
dtype: float64
...