Python 3.x 根据groupby中的比例填充分类NaN值
我正在使用一个完全由分类特征组成的数据集 只有一列缺少值:8124列中有2480列 我可以根据现有分类值的百分比成功填充NaN值:Python 3.x 根据groupby中的比例填充分类NaN值,python-3.x,pandas,pandas-groupby,Python 3.x,Pandas,Pandas Groupby,我正在使用一个完全由分类特征组成的数据集 只有一列缺少值:8124列中有2480列 我可以根据现有分类值的百分比成功填充NaN值: print(df['stalk-root'].value_counts(normalize=True), '\n') 收益率: b 0.669029 e 0.198441 c 0.098512 r 0.034018 e b 0.550459 e 0.247706
print(df['stalk-root'].value_counts(normalize=True), '\n')
收益率:
b 0.669029
e 0.198441
c 0.098512
r 0.034018
e b 0.550459
e 0.247706
c 0.146789
r 0.055046
p b 0.860853
e 0.118738
c 0.020408
然后,我使用这些百分比来填充缺少的值:
# https://stackoverflow.com/questions/38934140/fill-missing-values-by-a-ratio-of-other-values-in-pandas
df['stalk-root'] = df['stalk-root'].fillna(pd.Series(np.random.choice(['b', 'e', 'c', 'r'],
p=[0.669029, 0.198441, 0.098512, 0.034018], size=len(df))))
它工作得很好
然而,我很好奇,如果我按“class”列分组,df['stack-root']列的值_计数会是什么样子
print(df.groupby('class')['stalk-root'].value_counts(normalize=True), '\n')
收益率:
b 0.669029
e 0.198441
c 0.098512
r 0.034018
e b 0.550459
e 0.247706
c 0.146789
r 0.055046
p b 0.860853
e 0.118738
c 0.020408
这是一个相当大的区别。足够大,我现在想将我的NaN填充过程修改为第一个
按类别分组,然后按百分比填充,如上所述
我以前用数值列和mean()做过这项工作,但不同之处在于我是手动完成的
根据值_计数的结果(normalize=True),在np.random.choice()中填充百分比
我不知道该怎么说:groupby类,运行['stape-root'].value\u counts(normalize=True),然后获取这些值并输入fillna(np.random.choice(),就像我上面做的那样
我将有两组完全不同的填充值,“r”只出现在其中一个中
一个是(对于“e”类):
另一个(对于“p”类)为:
我遇到的第二个问题是size=len(df)。这必须是每个分组的大小(我假设),并且它们的大小不同
也许我误解了,但你不能这样做:
class_e = pd.Series(np.random.choice(['b', 'e', 'c', 'r'],
p=[0.550459, 0.247706, 0.146789, 0.055046], size=len(df)))
class_p = pd.Series(np.random.choice(['b', 'e', 'c'],
p=[0.860853, 0.118738, 0.020408], size=len(df))
df.loc[df['class'] == e, 'stalk-root'] = df['stalk-root'].fillna(class_e)
df.loc[df['class'] == p, 'stalk-root'] = df['stalk-root'].fillna(class_p)
下面是一个使用
groupby
was_null = df['stalk-root'].isna()
for _, gdf in df.groupby('class')['stalk-root']:
vc = gdf.value_counts(normalize=True)
df.loc[gdf.loc[gdf.isna()].index, 'stalk-root'] = (
np.random.choice(vc.index, gdf.isna().sum(), p=vc)
)
验证输出
# old distribution
print(df[was_null].groupby('class')['stalk-root'].value_counts(normalize=True))
class stalk-root
e b 0.561111
e 0.236111
c 0.140278
r 0.062500
p b 0.865341
e 0.117045
c 0.017614
Name: stalk-root, dtype: float64
# new distribution
print(df.groupby('class')['stalk-root'].value_counts(normalize=True))
class stalk-root
e b 0.552281
e 0.245722
c 0.145675
r 0.056321
p b 0.862870
e 0.117978
c 0.019152
Name: stalk-root, dtype: float64
你能提供一个例子吗?比如说
df[['class','stable root']]].head(50)。为了_dict()
@RichieV,我必须编辑我的问题以适应你要求的输出。见上文。我使用的是Kaggle的蘑菇.csv数据集。该数据集中没有NaN
s…下载后你修改了吗?df.info()
数据集中没有空值。范围索引:8124个条目,0到8123
&所有列都有8124个非空值
valuese_size=df[df['class']==e,:].size。如果我使用e_size=len(df[df['class']='e'])
错误已解决,但结果不正确。您的初始解决方案似乎是正确的。它必须在整个df中循环,因为受影响的行可能位于任何位置。起初我没有意识到。如果您修改的解决方案包含在groupby()中对象,那么我认为它是正确的。我甚至可以通过注释掉df.loc[df['class']==e,'stable root']]
行,一次一行,来查看第一个解决方案的每个部分到底填充了多少行。抱歉,我不太明白。如果你想在groupby@RichieV的解决方案中使用它,应该接受:)这对我来说无关紧要。你最初的解决方案很有效。删除编辑以将初始解决方案放回原位。