图1, 去重前后效果示例
这个不能直接由
drop_duplicates()
,那就写代码自己实现吧,因为是根据uid去重,我的思路是对uid进行循环,把uid相同的聚在一起,在if条件中选择保存的行并把name整合起来,建个新表保存去重后的行,
ndf=pd.DataFrame(columns=df.columns) #根据df的列名建一个空表ndf
uids=set(df['uid'])
for u in uids:
one=df.loc[df['uid']==u] #获取所有uid等于u的行,之后只会保存一行
#在这里写if然后只保留一行,然后concat到ndf上,实现只保留一行
olst=list(one['name']) #或者用set
zero=one.iloc[[0]] #iloc[行号]是series iloc[[行号]]是dataframe
#zero['name']=str(olst)
if len(olst)>1: #等于1的就不用改了
zero['name']=str(olst) #or =''.join(olst)
ndf=pd.concat([ndf,zero]) #把选出来的zero加到ndf里
我是用了一个for循环去遍历的,如果有更优雅的实现欢迎指教呀。
更深入一些,如果没有某一列可以作为主键呢?存在一个表,除name之外,其他的列都相同算重复行,这些列有文本有数值型,但是不能拿其中任何列作主键,实现上面的去重合并name,怎么办?一个个比对是O(n^2),我目前的思路时用除name之外的列合并形成一个字符串型的新列,拿这列做主键,用上面的代码片段。合并之后再删掉之前建的新列保持数据的格式。
关于python中的drop_duplicates(subset=None, keep='first', inplace=False)
,一些基础的去重需求直接用这个函数就好,它有三个参数:
subset指定根据哪些列去重,默认是根据所有列,也就是当两行的所有列都一样时满足去重条件;