python pandas:删除列A的重复项,将行的最高值保留在列B中


160

我在A列中有一个具有重复值的数据框。我想删除重复项,将行的最高值保留在B列中。

所以这:

A B
1 10
1 20
2 30
2 40
3 10

应该变成这样:

A B
1 20
2 40
3 10

Wes添加了一些不错的功能来删除重复项:http ://wesmckinney.com/blog/?p=340 。但是AFAICT是专为精确重复而设计的,因此没有提及选择保留哪些行的标准。

我猜想可能有一个简单的方法可以做到这一点-可能就像在删除重复项之前对数据帧进行排序一样简单-但我不知道groupby的内部逻辑足以弄清楚它。有什么建议?


1
请注意,问题中的URL显示为EOL。
DaveL17

有关惯用且高效的方式,请参见下面的解决方案
泰德·彼得鲁

Answers:


193

这需要最后一个。虽然不是最大:

In [10]: df.drop_duplicates(subset='A', keep="last")
Out[10]: 
   A   B
1  1  20
3  2  40
4  3  10

您还可以执行以下操作:

In [12]: df.groupby('A', group_keys=False).apply(lambda x: x.loc[x.B.idxmax()])
Out[12]: 
   A   B
A       
1  1  20
2  2  40
3  3  10

12
小提示:colstake_last参数已弃用,并已由subsetkeep参数代替。pandas.pydata.org/pandas-docs/version/0.17.1/generated/...
Jezzamon

正如@Jezzamon所说,FutureWarning: the take_last=True keyword is deprecated, use keep='last' instead
tumultous_rooster

1
有没有不使用的理由df.sort_values(by=['B']).drop_duplicates(subset=['A'], keep='last')?我的意思是,这个sort_values对我来说似乎很安全,但我不知道它是否确实如此。
小鲍比表

4
现在这个答案已经过时了。请参阅下面的@Ted Petrou的答案。
cxrodgers 17-04-27

如果要使用此代码,但如果中有多个列,则group_by可以添加,.reset_index(drop=True) df.groupby(['A','C'], group_keys=False).apply(lambda x: x.ix[x.B.idxmax()]).reset_index(drop=True)这将重置索引,因为它的默认值将是从'A''C'
Hamri Said

79

首要的答案是做太多的工作,对于较大的数据集来说似乎很慢。 apply速度慢,应尽可能避免。ix已弃用,也应避免使用。

df.sort_values('B', ascending=False).drop_duplicates('A').sort_index()

   A   B
1  1  20
3  2  40
4  3  10

或简单地按所有其他列分组并获取所需的最大列。 df.groupby('A', as_index=False).max()


1
这实际上是一个砍刀方法。我想知道是否可以lamba在删除时通过使用某些函数来概括它。例如,我如何只删除比那些重复值的平均值小的值。
德克斯特(Dexter)

15

最简单的解决方案:

要基于一列删除重复项:

df = df.drop_duplicates('column_name', keep='last')

要基于多个列删除重复项:

df = df.drop_duplicates(['col_name1','col_name2','col_name3'], keep='last')

1
最佳解决方案。谢谢。
Flavio

乐意效劳。@Flavio
吉尔·巴乔

我的数据框有10列,我使用此代码从三列中删除了重复项。但是,它从其余列中删除了行。有什么方法只能删除最后4列的重复项吗?
索非亚

2
但是OP希望将最高值保留在B列中。如果您首先进行排序,这可能会起作用。但这基本上是Ted Petrou的答案。
Teepeemm

7

试试这个:

df.groupby(['A']).max()

1
您知道重新编制索引以使其看起来像原始DataFrame的最佳习惯吗?当你忍者要我的时候,我试图弄清楚。:^)
DSM 2012年

4
整齐。如果数据框包含更多列(例如C,D,E)怎么办?在这种情况下,Max似乎不起作用,因为我们需要指定B是唯一需要最大化的列。
2012年

1
@DSM检查原始问题中的链接。有一些代码可以重新索引分组的数据框。
2012年

5

我会先对数据框进行排序,然后将B列降序,然后删除A列的重复项并保留在第一位

df = df.sort_values(by='B', ascending=False)
df = df.drop_duplicates(subset='A', keep="first")

没有任何分组



1

我认为在您的情况下,您确实不需要groupby。我将按降序排列您的B列,然后在A列中删除重复项,如果您愿意,还可以像这样创建一个新的美观索引:

df.sort_values('B', ascending=False).drop_duplicates('A').sort_index().reset_index(drop=True)

这与其他帖子有何不同?
DJK

1

这是我必须解决的一个变体,值得分享:对于其中的每个唯一字符串,columnA我想在中找到最常见的关联字符串columnB

df.groupby('columnA').agg({'columnB': lambda x: x.mode().any()}).reset_index()

.any()是否有对应的模式领带挑选一个。(请注意,.any()在一系列int返回布尔值,而不是选择其中一个。)

对于原始问题,相应的方法简化为

df.groupby('columnA').columnB.agg('max').reset_index()


0

当已有的帖子回答了这个问题时,我做了一点改动,添加了在其上应用了max()函数的列名,以提高代码的可读性。

df.groupby('A', as_index=False)['B'].max()

请为您的答案提供更多背景信息,解释它们的工作原理以及为什么它们比已有问题的答案优越或互补。如果他们没有提供附加值,请不要在旧问题上发布其他答案。最后,请通过缩进将代码格式化为代码块。
WhoIsJack

0

最简单的方法:

# First you need to sort this DF as Column A as ascending and column B as descending 
# Then you can drop the duplicate values in A column 
# Optional - you can reset the index and get the nice data frame again
# I'm going to show you all in one step. 

d = {'A': [1,1,2,3,1,2,3,1], 'B': [30, 40,50,42,38,30,25,32]}
df = pd.DataFrame(data=d)
df

    A   B
0   1   30
1   1   40
2   2   50
3   3   42
4   1   38
5   2   30
6   3   25
7   1   32


df = df.sort_values(['A','B'], ascending =[True,False]).drop_duplicates(['A']).reset_index(drop=True)

df

    A   B
0   1   40
1   2   50
2   3   42

-1

这也可以:

a=pd.DataFrame({'A':a.groupby('A')['B'].max().index,'B':a.groupby('A')       ['B'].max().values})

尽管此代码段可以解决问题,但提供说明确实有助于提高您的帖子质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。也请尽量不要在代码中加入解释性注释,这会降低代码和解释的可读性!
马丁·图尔诺伊

-8

我不打算给你全部答案(我不认为你正在寻找的解析反正写文件的一部分),但是关键的暗示就足够了:使用Python的set()功能,然后sorted().sort()加上.reverse()

>>> a=sorted(set([10,60,30,10,50,20,60,50,60,10,30]))
>>> a
[10, 20, 30, 50, 60]
>>> a.reverse()
>>> a
[60, 50, 30, 20, 10]

8
也许我在这个问题上是错的,但是将熊猫DataFrame重新设置为一个集合,然后再转换回它似乎是解决此问题的非常低效的方法。我正在进行日志分析,因此将其应用于一些非常大的数据集。
2012年

抱歉,对于这种特殊情况我不太了解,所以可能我的一般答案对您的问题不会太有效。
Abhranil Das 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.