问题描述
与此 post 类似,我正在删除缺失数据超过 50% 的行以获得更可靠和完整的数据集
# Keep only the rows with at least x% non-NA values
# calculate threshold
numOfFeatures=38 # num of features in dataset
x=round(numOfFeatures*0.5) #50%
dfWithDroppedRows = df.dropna(thresh=x)
但是,我有一个不平衡的数据集,其中大多数类占我数据集的近 93%
df['y'].value_counts(normalize=True) * 100
No 92.769441
Yes 7.230559
因此,我想编辑上面的代码以仅从多数类的样本中删除缺失数据超过 50% 的行,这样我就不会丢失少数类的样本。
为此,我尝试过:
dfWithDroppedRows = df[df['y'] == 'No'].dropna(thresh=x)
但这导致 dfWithDroppedRows 只包含来自多数类的减少行,而不包含来自少数类的样本。我想我可以通过将 dfWithDroppedRows 与 df[df['y'] == 'Yes'] 连接来解决这个问题,但我觉得应该有一种更直接的方法来做到这一点。有什么建议吗?
解决方法
在我看来,连接两个 DataFrame 并不是一个坏主意,但如果你不喜欢它,这是我的建议。
mask_majority = df.eval("y == 'No'")
mask_missing = df.isna().sum(axis="columns") >= x
import numpy as np
mask_drop = np.logical_and(mask_majority,mask_missing)
mask_keep = np.logical_not(mask_drop)
dfWithDroppedRows = df.loc[mask_keep,:]
基本上,我为多数类创建了一个掩码,并为所有缺失值超过 x
的行创建了一个掩码。
然后我将这两个掩码组合起来得到一个掩码,其中包含所有不能删除的行,然后我使用 .loc
得到只包含那些行的 DataFrame。
顺便说一句,如果您决定使用连接两个 DataFrame 的初始解决方案,我会改用 query
方法,它更惯用:
df_majority_droppedRows = df.query("y == 'No'").dropna(thresh=x)
df_minority = df.query("y == 'Yes'")
dfWithDroppedRows = pd.concat([df_majority_droppedRows,df_minority])