Pandas - 按ID分组和删除重复,阈值为

时间:2017-05-01 03:03:31

标签: python pandas group-by duplicates 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] })

5 个答案:

答案 0 :(得分:7)

您可以使用duplicated确定行级别重复项,然后在用户ID'上执行groupby。确定用户ID'级别重复,然后相应地下降。

在没有门槛的情况下放弃:

df = df[~df.duplicated(['userid', 'itemid']).groupby(df['userid']).transform('any')]

要删除阈值,请在keep=False中使用duplicated,并对布尔列求和并与阈值进行比较。例如,阈值为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

答案 1 :(得分:5)

filter

是为此做的。您可以传递一个返回布尔值的函数,该函数确定该组是否通过了过滤器。

filtervalue_counts
最具概括性和直观性的

df.groupby('userid').filter(lambda x: x.itemid.value_counts().max() < 2)

filteris_unique
寻找n < 2

时的特殊情况
df.groupby('userid').filter(lambda x: x.itemid.is_unique)

   userid  itemid
4       2       1
5       2       2
6       2       3

答案 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

合并结果并保留“好”行:

combined = df.merge(pd.DataFrame(viewed).reset_index())
combined[combined[0]][['userid','itemid']]
#   userid  itemid
#4       2       1
#5       2       2
#6       2       3

答案 3 :(得分:2)

# 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]

答案 4 :(得分:0)

我不知道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

希望它有所帮助。