【发布时间】:2020-08-06 05:22:46
【问题描述】:
我正在尝试使用 df.loc[df.groupby(keys)['column'].idxmax()] 按最大值从组中选择行。
不过,我发现df.groupby(keys)['column'].idxmax() 在我大约 2700 万行的数据集上花费了很长时间。有趣的是,在我的数据集上运行 df.groupby(keys)['column'].max() 只需要 13 秒,而运行 df.groupby(keys)['column'].idxmax() 需要 55 分钟。我不明白为什么返回行的索引比从行返回值要长 250 倍。也许我可以做些什么来加快 idxmax?
如果没有,是否有另一种方法可以比使用 idxmax 更快地按最大值从组中选择行?
有关其他信息,我使用了两个键,并在 groupby 和 idxmax 操作之前对这些键上的数据帧进行了排序。这是它在 Jupyter Notebook 中的样子:
import pandas as pd
df = pd.read_csv('/data/Broadband Data/fbd_us_without_satellite_jun2019_v1.csv', encoding='ANSI', \
usecols=['BlockCode', 'HocoNum', 'HocoFinal', 'TechCode', 'Consumer', 'MaxAdDown', 'MaxAdUp'])
%%time
df = df[df.Consumer == 1]
df.sort_values(['BlockCode', 'HocoNum'], inplace=True)
print(df)
HocoNum HocoFinal BlockCode TechCode
4631064 130077 AT&T Inc. 10010201001000 10
4679561 130077 AT&T Inc. 10010201001000 11
28163032 130235 Charter Communications 10010201001000 43
11134756 131480 WideOpenWest Finance, LLC 10010201001000 42
11174634 131480 WideOpenWest Finance, LLC 10010201001000 50
... ... ... ... ...
15389917 190062 Broadband VI, LLC 780309900000014 70
10930322 130081 ATN International, Inc. 780309900000015 70
15389918 190062 Broadband VI, LLC 780309900000015 70
10930323 130081 ATN International, Inc. 780309900000016 70
15389919 190062 Broadband VI, LLC 780309900000016 70
Consumer MaxAdDown MaxAdUp
4631064 1 6.0 0.512
4679561 1 18.0 0.768
28163032 1 940.0 35.000
11134756 1 1000.0 50.000
11174634 1 1000.0 50.000
... ... ... ...
15389917 1 25.0 5.000
10930322 1 25.0 5.000
15389918 1 25.0 5.000
10930323 1 25.0 5.000
15389919 1 25.0 5.000
[26991941 rows x 7 columns]
Wall time: 21.6 s
%time df.groupby(['BlockCode', 'HocoNum'])['MaxAdDown'].max()
Wall time: 13 s
BlockCode HocoNum
10010201001000 130077 18.0
130235 940.0
131480 1000.0
10010201001001 130235 940.0
10010201001002 130077 6.0
...
780309900000014 190062 25.0
780309900000015 130081 25.0
190062 25.0
780309900000016 130081 25.0
190062 25.0
Name: MaxAdDown, Length: 20613795, dtype: float64
%time df.groupby(['BlockCode', 'HocoNum'])['MaxAdDown'].idxmax()
Wall time: 55min 24s
BlockCode HocoNum
10010201001000 130077 4679561
130235 28163032
131480 11134756
10010201001001 130235 28163033
10010201001002 130077 4637222
...
780309900000014 190062 15389917
780309900000015 130081 10930322
190062 15389918
780309900000016 130081 10930323
190062 15389919
Name: MaxAdDown, Length: 20613795, dtype: int64
您会在第一行数据中看到,在同一个 BlockCode 中有两个 AT&T 条目,一个用于 6Mbps 的 MaxAdDown,一个用于 18Mbps。我想保留 18Mbps 行并删除 6Mbps 行,以便每个 BlockCode 的每个公司都有一行具有最大 MaxAdDown 值。我需要整行,而不仅仅是 MaxAdDown 值。
【问题讨论】:
-
try .apply(lambda x: x.index.iloc[np.argmax(x['MaxAdDown'])]) 可能会工作并且更快
-
检查随机样本,确实有点快(虽然 iloc 是一个错误,丢失它)但请参阅我的答案以获得更快的解决方案
-
谢谢!我在相同条件下进行了时间测试,确实看到了一些改进——从 55 分钟缩短了 43 分钟,大约提高了 22%。不幸的是,这不适用于交互式应用程序,所以我必须重新考虑一些事情。我也很困惑为什么 .max() 比 .idxmax() 工作得这么快。
-
查看我对不同解决方案的回答,对于为什么会猜测 max 是在 cyton 中实现的,请查看 pandas 源代码以尝试找出
标签: python pandas dataframe max