如何使用groupby避免python中的循环

Posted

技术标签:

【中文标题】如何使用groupby避免python中的循环【英文标题】:how to use groupby to avoid loop in python 【发布时间】:2013-12-05 03:58:42 【问题描述】:

数据中有几列,三列分别命名为“candidate_id”、“enddate”、“TitleLevel”。

在同一id内,如果enddate相同,我会删除下一级记录。

例如,给定:

candidate_id   startdate     enddate   TitleLevel
    1          2012.1.1      2013.5.1     2
    1          2011.1.1      2013.5.1     4
    1          2008.12.1     2010.1.1     3
    2          2010.10.1     2012.12.1    2

我想要的是:

candidate_id   startdate     enddate   TitleLevel
    1          2011.1.1      2013.5.1     4
    1          2008.12.1     2010.1.1     3
    2          2010.10.1     2012.12.1    2

我将删除candidate_id=1enddate=2013.5.1titlelevel=2

我想出了一个循环。

for i in range(nrow-2,-1, -1):
    if (JobData['enddate'][i] == JobData['enddate'][i+1] 
           and JobData['candidate_id'][i] == JobData['candidate_id'][i+1] 
           and pd.notnull(JobData['enddate'][i]):
        if JobData['TitleLevel'][i] > JobData['TitleLevel'][i+1]:
            JobData= JobData.drop(i+1)
        else:
            JobData= JobData.drop(i) 

循环确实需要一些时间来删除冗余行。有更快的方法吗?

【问题讨论】:

如果你能在代码中给出一些测试数据,你会更容易回答你的问题。话虽如此,groupby 非常好用。只需记住在将数据列表传递给函数之前对其进行排序 不仅仅是熊猫。我只是想找到一种方法来加速代码,而不使用 for 循环和 if else。测试数据在“说”下面。在candidate_id=1,enddate=2013.5.1,我想删除TitleLevel较低的行。 @user3013706,是的,但是用pandas 标记非常有帮助,因为熟悉它的人会看到你的问题 @user3013706 当你使用pandas时,可以根据pandas api给你建议,而不仅仅是使用一般的python内置 这段代码的目的是建立一个统计模型。所以我使用熊猫读入 csv 文件。好的,我会把“熊猫”放在标签里:) 【参考方案1】:

假设数据按开始日期排序(至少在每个组内),您可以使用groupby last:

In [11]: df.groupby(['candidate_id', 'enddate'], as_index=False).last()
Out[11]: 
   candidate_id    enddate  startdate  TitleLevel
0             1   2010.1.1  2008.12.1           3
1             1   2013.5.1   2011.1.1           4
2             2  2012.12.1  2010.10.1           2

【讨论】:

排序需要时间,所以我没有按开始日期对数据进行排序。我想要做的是将具有最高 TitleLevel 的数据保留在相同的候选 ID 和相同的结束日期中。你有什么想法可以做到这一点,但没有对开始日期进行排序?谢谢!【参考方案2】:

如果你的数据结构和你描述的完全一样,你可以使用groupby/max:

>>> df
   candidate_id    enddate  TitleLevel
0             1   2013.5.1           2
1             1   2013.5.1           4
2             1   2010.1.1           3
3             2  2012.12.1           2
>>> df.groupby(['candidate_id','enddate']).max().reset_index()
   candidate_id    enddate  TitleLevel
0             1   2010.1.1           3
1             1   2013.5.1           4
2             2  2012.12.1           2

这里 groupby 将具有相等 candidate_idenddate 的行分组,max() 计算每个组内的最大 TitleLevel。结果与删除所有其他值的行相同。

如果你有更多的列,

>>> df
   candidate_id    enddate  TitleLevel other_column
0             1   2013.5.1           2          foo
1             1   2013.5.1           4          bar
2             1   2010.1.1           3       foobar
3             2  2012.12.1           2       barfoo

如果必须保留行顺序,您可以获得具有最大值的行的索引,而无需排序:

>>> idx = df.groupby(['candidate_id','enddate'], sort=False)['TitleLevel'].agg(lambda x: x.idxmax())

并使用ix过滤所需的行:

>>> df.ix[idx]
   candidate_id    enddate  TitleLevel other_column
1             1   2013.5.1           4          bar
2             1   2010.1.1           3       foobar
3             2  2012.12.1           2       barfoo

【讨论】:

但是如果我还想保持“enddate”的原始顺序。您的代码似乎对候选 ID 中的结束日期进行了排序。还有一些其他的列,我只是提取这些例如.. @user3013706 您可以使用 sort=False 参数和 ix/idxmax 而不是 max。查看更新的代码 就我而言,我认为 groupby(['candidate_id','enddate'],sort=False)['TitleLevel'].agg(lambda x:x.max()) 是正确的, bc 它不需要最大化它的索引。但是,使用代码后,其他列(除了candidate_id、enddate、TitleLevel)都不见了。

以上是关于如何使用groupby避免python中的循环的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 .join() 避免在循环中连接字符串? - Python

如何在python中的groupby中为lambda函数设置名称标题[重复]

我如何编写一个 python/pandas 循环来将 sql 查询中的日期增加一天

如何避免R中特定多条件语句中的循环

如何避免循环中断?

如何在 python 中使用 Spark Data frame 和 GroupBy 派生 Percentile