熊猫用过滤器填充最常见的值?



给定一个包含两列的数据帧,如下所示:

| user_id | preference_id |
|---------|---------------|
| 1       | 1             |
| 1       | 2             |
| 1       | None          |
| 2       | 1             |
| 3       | 2             |
| 3       | 2             |
| 3       | None          |

如何用该user_id最常见的值填充preference_id缺失值?我当前的解决方案包括循环遍历所有唯一user_id,这些至少有一个preference_id缺失值和至少一个数据preference_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]
})

也就是说,其中一个user_id记录仅缺少preference_id

编辑 #2

在通过@anky_91尝试解决方案后,我能够通过首先过滤掉只有缺失值的用户来解决上面发布的边缘情况(因此,我无法推断缺失preference_id的用户(:

# Remove edge cases
ids = df.groupby('user_id').preference_id.count()
.where(lambda x: x > 0).dropna().to_frame().reset_index()
# User anky_91 solution
ids.groupby('user_id').preference_id.transform(lambda x: x.mode().iat[0])

可能有一种更有效、更优雅的方式来完成第一步,但这是可以的。慢部分是第二步,所以我可以接受这种形式的步骤#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)

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

最新更新