考虑到起始数据中已经存在的空值,我如何将NaN值随机引入到我的每一列的数据集中。
我想按列获取例如NaN值的20%。
例如:
如果我在数据集中有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]))
答案 0 :(得分:1)
我不确定最后一部分是什么意思(“降级太多”),但这是一种粗略的方法。
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
值的影响。
答案 1 :(得分:1)
除非您拥有庞大的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))
答案 2 :(得分:0)
这是一种使每列中的nan尽可能接近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
我已将其应用于整个数据集,但是您可以将其应用于所需的任何列。例如,如果您希望在y
和x1
列中使用15%的NaN,则可以调用df[['y','x1]].apply(input_nan, pct=.15)
答案 3 :(得分:0)
我想我参加聚会有点晚了,但如果有人需要更快的解决方案并在引入空值时考虑百分比值,这里是代码:
nan_percent = {'A':0.15, 'B':0.05, 'C':0.23}
for col, perc in nan_percent.items():
df['null'] = np.random.choice([0, 1], size=df.shape[0], p=[1-perc, perc])
df.loc[df['null'] == 1, col] = np.nan
df.drop(columns=['null'], inplace=True)