Случайно ввести значения NaN в кадре данных панд - PullRequest
0 голосов
/ 23 января 2019

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

Я хочу иметь, например, 20% значений NaN по столбцам.

Например:
Если в моем наборе данных есть 3 столбца: «A», «B» и «C» для каждого столбца, у меня есть коэффициент значений NaN, как мне вводить случайным образом значения NaN по столбцам, чтобы достичь 20% для столбца:

A: 10% nan
B: 15% nan
C: 8% nan

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

df = df.mask(np.random.choice([True, False], size=df.shape, p=[.20,.80]))

Ответы [ 3 ]

0 голосов
/ 23 января 2019

Если у вас нет гигантского DataFrame и скорость не вызывает беспокойства, простой и легкий способ сделать это - итерацией.

import pandas as pd
import numpy as np
import random

df = pd.DataFrame({'A':list(range(100)),'B':list(range(100)),'C':list(range(100))})
#before adding nan
print(df.head(10))

nan_percent = {'A':0.10, 'B':0.15, 'C':0.08}

for col in df:
    for i, row_value in df[col].iteritems():
        if random.random() <= nan_percent[col]:
            df[col][i] = np.nan
#after adding nan            
print(df.head(10))
0 голосов
/ 23 января 2019

Вот способ получить как можно ближе к 20% нан. В каждом столбце:

def input_nan(x,pct):
    n = int(len(x)*(pct - x.isna().mean()))
    idxs = np.random.choice(len(x), max(n,0), replace=False, p=x.notna()/x.notna().sum())
    x.iloc[idxs] = np.nan

df.apply(input_nan, pct=.2)

Сначала берется разница между NaN процентами, которые вы хотите, и процентными значениями NaN в вашем наборе данных. Затем он умножает его на длину столбца, что дает вам количество NaN значений, которые вы хотите вставить (n). Затем использует np.random.choice, который случайным образом выбирает n индексы, в которых нет NaN значений.

Пример:

df = pd.DataFrame({'y':np.random.randn(10), 'x1':np.random.randn(10), 'x2':np.random.randn(10)})
df.y.iloc[1]=np.nan
df.y.iloc[8]=np.nan
df.x2.iloc[5]=np.nan

#           y        x1        x2
# 0  2.635094  0.800756 -1.107315
# 1       NaN  0.055017  0.018097
# 2  0.673101 -1.053402  1.525036
# 3  0.246505  0.005297  0.289559
# 4  0.883769  1.172079  0.551917
# 5 -1.964255  0.180651       NaN
# 6 -0.247067  0.431622 -0.846953
# 7  0.603750  0.475805  0.524619
# 8       NaN -0.452400 -0.191480
# 9 -0.583601 -0.446071  0.029515

df.apply(input_nan)

#           y        x1        x2
# 0  2.635094  0.800756 -1.107315
# 1       NaN  0.055017  0.018097
# 2  0.673101 -1.053402  1.525036
# 3  0.246505  0.005297       NaN
# 4  0.883769  1.172079  0.551917
# 5 -1.964255       NaN       NaN
# 6 -0.247067  0.431622 -0.846953
# 7  0.603750       NaN  0.524619
# 8       NaN -0.452400 -0.191480
# 9 -0.583601 -0.446071  0.029515

Я применил его ко всему набору данных, но вы можете применить его к любому столбцу, который хотите. Например, если вы хотите 15% NaN в столбцах y и x1, вы можете позвонить df[['y','x1]].apply(input_nan, pct=.15)

0 голосов
/ 23 января 2019

Я не уверен, что вы подразумеваете под последней частью («слишком сильно деградирует»), но вот грубый способ сделать это.

import numpy as np
import pandas as pd

A = pd.Series(np.arange(99))

# Original missing rate (for illustration)
nanidx = A.sample(frac=0.1).index
A[nanidx] = np.NaN

###
# Complementing to 20%
# Original ratio
ori_rat = A.isna().mean()

# Adjusting for the dataframe without missing values
add_miss_rat = (0.2 - ori_rat) / (1 - ori_rat)

nanidx2 = A.dropna().sample(frac=add_miss_rat).index
A[nanidx2] = np.NaN

A.isna().mean()

Очевидно, что это не всегда будет ровно 20% ...

Обновление Применение его для всего фрейма данных

for col in df:
    ori_rat = df[col].isna().mean()

    if ori_rat >= 0.2: continue

    add_miss_rat = (0.2 - ori_rat) / (1 - ori_rat)
    vals_to_nan = df[col].dropna().sample(frac=add_miss_rat).index
    df.loc[vals_to_nan, col] = np.NaN

Обновление 2 Я внес исправление, чтобы учесть такжеэффект отбрасывания значений NaN при расчете коэффициента.

...