根据groupby值

时间:2016-03-21 06:34:13

标签: python python-3.x pandas dataframe

我有一个从SQL Server数据库中检索到的大型Pandas数据帧(> 100万行)。在少数情况下,一些记录具有重复的条目。除单个文本字段外,所有单元格都相同。看起来记录已经输入到数据库中,然后,稍后,该字段中添加了附加文本,并将记录作为单独的条目存储在数据库中。所以基本上,我想只保留带有最长文本字符串的记录。可以按如下方式创建数据库的简化版本:

tempDF = pd.DataFrame({ 'recordID': [1,2,3,3,4,5,6,6,6,7,7,8,9,10],
                        'text': ['abc', 'def', 'ghi', 'ghijkl', 'mto', 'per', 'st', 'stuvw', 'stuvwx', 'yz', 'yzab', 'cde', 'fgh', 'ijk']})

看起来像这样:

    recordID    text
0         21     abc
1         22     def
2         23     ghi
3         23  ghijkl
4         24     mno
5         25     pqr
6         26      st
7         26   stuvw
8         26  stuvwx
9         27      yz
10        27    yzab
11        28     cde
12        29     fgh
13        30     ijk

到目前为止,我已经识别出具有重复记录ID的行并计算了文本字段的长度:

tempDF['dupl'] = tempDF.duplicated(subset = 'recordID',keep=False)
tempDF['texLen'] = tempDF['text'].str.len()
print(tempDF)

生产:

    recordID    text   dupl  texLen
0         21     abc  False       3
1         22     def  False       3
2         23     ghi   True       3
3         23  ghijkl   True       6
4         24     mno  False       3
5         25     pqr  False       3
6         26      st   True       2
7         26   stuvw   True       5
8         26  stuvwx   True       6
9         27      yz   True       2
10        27    yzab   True       4
11        28     cde  False       3
12        29     fgh  False       3
13        30     ijk  False       3

我可以使用以下方法对所有基于recordID的dupl == True记录进行分组:

tempGrouped = tempDF[tempDF['dupl']==True].groupby('recordID')

分别打印每组:

for name, group in tempGrouped:
    print('n',name)
    print(group)

23
   recordID    text  dupl  texLen
2        23     ghi  True       3
3        23  ghijkl  True       6

26
   recordID    text  dupl  texLen
6        26      st  True       2
7        26   stuvw  True       5
8        26  stuvwx  True       6

27
    recordID  text  dupl  texLen
9         27    yz  True       2
10        27  yzab  True       4

我希望最终的数据帧包含dupl == False的记录,如果dupl == True,则只保留具有最长文本字段的复制。因此,最终的数据框应如下所示:

    recordID    text   dupl  texLen
0         21     abc  False       3
1         22     def  False       3
3         23  ghijkl   True       6
4         24     mno  False       3
5         25     pqr  False       3
8         26  stuvwx   True       6
10        27    yzab   True       4
11        28     cde  False       3
12        29     fgh  False       3
13        30     ijk  False       3

如何从原始数据框中仅删除recordID重复且texLen小于最大值的那些行?

1 个答案:

答案 0 :(得分:1)

您可以尝试在False列和idxmax列中找到concatsort_indexdupl的最大值的索引:

idx = tempDF[tempDF['dupl']==True].groupby('recordID')['texLen'].idxmax()   

print tempDF.loc[idx]
    recordID    text  dupl  texLen
3         23  ghijkl  True       6
8         26  stuvwx  True       6
10        27    yzab  True       4

print pd.concat([tempDF[tempDF['dupl']==False], tempDF.loc[idx]]).sort_index(0)
    recordID    text   dupl  texLen
0         21     abc  False       3
1         22     def  False       3
3         23  ghijkl   True       6
4         24     mto  False       3
5         25     per  False       3
8         26  stuvwx   True       6
10        27    yzab   True       4
11        28     cde  False       3
12        29     fgh  False       3
13        30     ijk  False       3

更简单的解决方案使用sort_valuesfirst,因为False的行具有唯一recordID(不重复):

df=tempDF.sort_values(by="texLen", ascending=False).groupby("recordID").first().reset_index()
print df   
   recordID    text   dupl  texLen
0        21     abc  False       3
1        22     def  False       3
2        23  ghijkl   True       6
3        24     mto  False       3
4        25     per  False       3
5        26  stuvwx   True       6
6        27    yzab   True       4
7        28     cde  False       3
8        29     fgh  False       3
9        30     ijk  False       3