Pandas - 按 id 分组并删除具有阈值的重复项
Pandas - group by id and drop duplicate with threshold
我有以下数据:
userid itemid
1 1
1 1
1 3
1 4
2 1
2 2
2 3
我想删除查看同一 itemID 两次以上的用户 ID。
例如,userid=1查看了两次itemid=1,因此我想删除userid=1的整条记录。但是,由于userid=2没有查看过同一个项目两次,我将保持userid=2不变。
所以我希望我的数据如下所示:
userid itemid
2 1
2 2
2 3
有人可以帮助我吗?
import pandas as pd
df = pd.DataFrame({'userid':[1,1,1,1, 2,2,2],
'itemid':[1,1,3,4, 1,2,3] })
按用户和项目对数据框进行分组:
views = df.groupby(['userid','itemid'])['itemid'].count()
#userid itemid
#1 1 2 <=== The offending row
# 3 1
# 4 1
#2 1 1
# 2 1
# 3 1
#Name: dummy, dtype: int64
找出谁只看过一次任何项目:
THRESHOLD = 2
viewed = ~(views.unstack() >= THRESHOLD).any(axis=1)
#userid
#1 False
#2 True
#dtype: bool
合并结果并保留 'good' 行:
combined = df.merge(pd.DataFrame(viewed).reset_index())
combined[combined[0]][['userid','itemid']]
# userid itemid
#4 2 1
#5 2 2
#6 2 3
您可以使用duplicated
确定行级重复项,然后在'userid'上执行groupby
确定'userid'级重复项,然后相应地删除。
无门槛下降:
df = df[~df.duplicated(['userid', 'itemid']).groupby(df['userid']).transform('any')]
要降低阈值,请在 duplicated
中使用 keep=False
,并对布尔列求和并与阈值进行比较。例如,阈值为 3:
df = df[~df.duplicated(['userid', 'itemid'], keep=False).groupby(df['userid']).transform('sum').ge(3)]
无阈值的结果输出:
userid itemid
4 2 1
5 2 2
6 2 3
# group userid and itemid and get a count
df2 = df.groupby(by=['userid','itemid']).apply(lambda x: len(x)).reset_index()
#Extract rows where the max userid-itemid count is less than 2.
df2 = df2[~df2.userid.isin(df2[df2.ix[:,-1]>1]['userid'])][df.columns]
print(df2)
itemid userid
3 1 2
4 2 2
5 3 2
如果你想在某个阈值下降,只需设置
df2.ix[:,-1]>threshold]
我不知道 Pandas
中是否有可用的函数来执行此任务。但是,我尝试了一个解决方法来解决您的问题。
这是完整的代码。
import pandas as pd
dictionary = {'userid':[1,1,1,1,2,2,2],
'itemid':[1,1,3,4,1,2,3]}
df = pd.DataFrame(dictionary, columns=['userid', 'itemid'])
selected_user = []
for user in df['userid'].drop_duplicates().tolist():
items = df.loc[df['userid']==user]['itemid'].tolist()
if len(items) != len(set(items)): continue
else: selected_user.append(user)
result = df.loc[(df['userid'].isin(selected_user))]
此代码将产生以下结果。
userid itemid
4 2 1
5 2 2
6 2 3
希望对您有所帮助。
filter
为此而生。您可以传递一个函数,该函数 returns 一个确定该组是否通过过滤器的布尔值。
filter
和 value_counts
最具概括性和直观性
df.groupby('userid').filter(lambda x: x.itemid.value_counts().max() < 2)
filter
和 is_unique
寻找n < 2
时的特殊情况
df.groupby('userid').filter(lambda x: x.itemid.is_unique)
userid itemid
4 2 1
5 2 2
6 2 3
我有以下数据:
userid itemid
1 1
1 1
1 3
1 4
2 1
2 2
2 3
我想删除查看同一 itemID 两次以上的用户 ID。 例如,userid=1查看了两次itemid=1,因此我想删除userid=1的整条记录。但是,由于userid=2没有查看过同一个项目两次,我将保持userid=2不变。
所以我希望我的数据如下所示:
userid itemid
2 1
2 2
2 3
有人可以帮助我吗?
import pandas as pd
df = pd.DataFrame({'userid':[1,1,1,1, 2,2,2],
'itemid':[1,1,3,4, 1,2,3] })
按用户和项目对数据框进行分组:
views = df.groupby(['userid','itemid'])['itemid'].count()
#userid itemid
#1 1 2 <=== The offending row
# 3 1
# 4 1
#2 1 1
# 2 1
# 3 1
#Name: dummy, dtype: int64
找出谁只看过一次任何项目:
THRESHOLD = 2
viewed = ~(views.unstack() >= THRESHOLD).any(axis=1)
#userid
#1 False
#2 True
#dtype: bool
合并结果并保留 'good' 行:
combined = df.merge(pd.DataFrame(viewed).reset_index())
combined[combined[0]][['userid','itemid']]
# userid itemid
#4 2 1
#5 2 2
#6 2 3
您可以使用duplicated
确定行级重复项,然后在'userid'上执行groupby
确定'userid'级重复项,然后相应地删除。
无门槛下降:
df = df[~df.duplicated(['userid', 'itemid']).groupby(df['userid']).transform('any')]
要降低阈值,请在 duplicated
中使用 keep=False
,并对布尔列求和并与阈值进行比较。例如,阈值为 3:
df = df[~df.duplicated(['userid', 'itemid'], keep=False).groupby(df['userid']).transform('sum').ge(3)]
无阈值的结果输出:
userid itemid
4 2 1
5 2 2
6 2 3
# group userid and itemid and get a count
df2 = df.groupby(by=['userid','itemid']).apply(lambda x: len(x)).reset_index()
#Extract rows where the max userid-itemid count is less than 2.
df2 = df2[~df2.userid.isin(df2[df2.ix[:,-1]>1]['userid'])][df.columns]
print(df2)
itemid userid
3 1 2
4 2 2
5 3 2
如果你想在某个阈值下降,只需设置
df2.ix[:,-1]>threshold]
我不知道 Pandas
中是否有可用的函数来执行此任务。但是,我尝试了一个解决方法来解决您的问题。
这是完整的代码。
import pandas as pd
dictionary = {'userid':[1,1,1,1,2,2,2],
'itemid':[1,1,3,4,1,2,3]}
df = pd.DataFrame(dictionary, columns=['userid', 'itemid'])
selected_user = []
for user in df['userid'].drop_duplicates().tolist():
items = df.loc[df['userid']==user]['itemid'].tolist()
if len(items) != len(set(items)): continue
else: selected_user.append(user)
result = df.loc[(df['userid'].isin(selected_user))]
此代码将产生以下结果。
userid itemid
4 2 1
5 2 2
6 2 3
希望对您有所帮助。
filter
为此而生。您可以传递一个函数,该函数 returns 一个确定该组是否通过过滤器的布尔值。
filter
和 value_counts
最具概括性和直观性
df.groupby('userid').filter(lambda x: x.itemid.value_counts().max() < 2)
filter
和 is_unique
寻找n < 2
df.groupby('userid').filter(lambda x: x.itemid.is_unique)
userid itemid
4 2 1
5 2 2
6 2 3