Pandas 是否用过滤器的最常用值填充缺失值?
给定一个包含两列的数据帧,如下所示:Pandas 是否用过滤器的最常用值填充缺失值?,pandas,dataframe,data-science,Pandas,Dataframe,Data Science,给定一个包含两列的数据帧,如下所示: | user_id | preference_id | |---------|---------------| | 1 | 1 | | 1 | 2 | | 1 | None | | 2 | 1 | | 3 | 2 | | 3 | 2 | | 3
| user_id | preference_id |
|---------|---------------|
| 1 | 1 |
| 1 | 2 |
| 1 | None |
| 2 | 1 |
| 3 | 2 |
| 3 | 2 |
| 3 | None |
如何用该用户id
的最频繁值来填充首选项id
中缺少的值?我当前的解决方案包括在所有唯一的用户id
上循环,这些用户id至少有一个首选项id
缺少值,并且至少有一个首选项id
的实例包含以下数据:
# Find all rows where preference_id is missing
pref_na = df.loc[df.preference_id.isna()]
# Find all users that have at least one missing and one not missing
# value for preference_id
users = df.loc[
(~df.preference_id.isna()) & (df.user_id.isin(pref_na))
]
for id in users.user_id.unique():
# Find most common preference_id for a user
top_pref = df.loc[
(df.user_id == id) & (~df.preference_id.isna()),
['preference_id']
]
if top_pref.shape[0] == 0:
continue
top_pref = top_pref.preference_id.mode()[0]
# Fill in missing prefs with top_pref
df.loc[
(df.user_id == id) & (df.preference_id.isna()),
'preference_id'] = top_pref
有没有一种本地的或矢量化的方法来实现这一点
编辑
下面是一个@anky_91的建议出现错误的示例:
df = pd.DataFrame({
'user_id': [1, 1, 1, 2, 3, 3, 3],
'preference_id': [1, 2, None, None, 2, 2, None]
})
也就是说,其中一个用户id
记录只缺少首选项id
s
编辑#2
在使用@anky_91的解决方案进行试验后,我能够通过首先过滤掉只有缺失值的用户(因此,我无法推断缺失的偏好id的用户)来解决上面发布的边缘情况:
可能有一种更高效、更优雅的方法来完成第一步,但这样就可以了。缓慢的部分是第二步,因此我同意第1步的形式。使用:
s=df.groupby('user_id')['preference_id'].transform(lambda x: x.mode().iat[0])
df.preference_id=df.preference_id.fillna(s)
print(df)
另一种方式:
m=(df.groupby('user_id')['preference_id'].apply(lambda x: x.mode(dropna=False).iat[0])
.reset_index(name='Mode'))
df.merge(m,on='user_id')
如果有两个(或更多)最常见的值怎么办?
top\u pref=top\u pref.preference\u id.mode()[0]
如果有多个相同频率的pref,我只取其中的一个。这没关系,这看起来很有希望。但是,发送到lambda的值似乎是一个带有单个首选项\u id
的序列。在某些情况下,给定的user\u id
有5个pref值,只有一个pref值为nan
,但lambda正好传递给nan
,因此x.mode().iat[0]
返回索引0超出大小为0的轴0的界限。
@rodrigo silveira it Groupuser\u id
,你能用一个例子详细说明这一点吗?贴了一个例子
user_id preference_id
0 1 1.0
1 1 2.0
2 1 1.0
3 2 1.0
4 3 2.0
5 3 2.0
6 3 2.0
m=(df.groupby('user_id')['preference_id'].apply(lambda x: x.mode(dropna=False).iat[0])
.reset_index(name='Mode'))
df.merge(m,on='user_id')
user_id preference_id Mode
0 1 1.0 1.0
1 1 2.0 1.0
2 1 NaN 1.0
3 2 NaN NaN
4 3 2.0 2.0
5 3 2.0 2.0
6 3 NaN 2.0