【问题标题】:Efficient max selection in pandas dataframe with selection condition具有选择条件的熊猫数据框中的有效最大选择
【发布时间】:2015-03-09 11:54:43
【问题描述】:

我有一个带有列(除其他外)user_idstart_time 的 pandas 数据框。我想高效且易读地找到与每个用户的最大值 start_time 关联的所有行。

例如,如果这是我的数据:

user_id   start_time   A    B    C
1         37           a    b    c
1         45           d    e    f
1         45           g    h    i
2         58           j    k    l
2         17           m    n    o
2         58           p    q    r
3          2           s    t    u

那么我希望找到

user_id   start_time   A    B    C
1         45           d    e    f
1         45           g    h    i
2         58           j    k    l
2         58           p    q    r
3          2           s    t    u

我一直在想出有点像Conditional selection of data in a pandas DataFrame 的解决方案,但是会找到带有最新start timeuser_id,而不是选择每个用户最大start_time 的表。

当然,如果我手动迭代DataFrame很容易,但效率很低。

感谢您的任何指点。

为了方便以后的读者,这样生成数据框:

columns = ['user_id', 'start_time', 'A', 'B', 'C']
LoL = [
    [1, 37, 'a', 'b', 'c'],
    [1, 45, 'd', 'e', 'f'],
    [1, 45, 'g', 'h', 'i'],
    [2, 58, 'j', 'k', 'l'],
    [2, 17, 'm', 'n', 'o'],
    [2, 58, 'p', 'q', 'r'],
    [3, 2, 's', 't', 'u']]
pd.DataFrame = (LoL, columns=columns)

【问题讨论】:

  • 我很想知道 groupby() 和 merge() 方法将如何在您的大框架上执行,而不是下面的其他答案。你能试试吗? g = df.groupby('user_id', as_index=False)['start_time'].max() df.merge(g)

标签: python python-3.x pandas


【解决方案1】:

您可以按 user_id 列分组,然后调用apply 并传递一个 lambda,它过滤开始时间等于最大值的结果,我们希望从中生成一个布尔索引。然后我们可以调用reset_index,但是由于 groupby 被过滤的方式,我们会收到重复列的错误,所以我们必须删除这个重复的列:

In [66]:

gp = df.groupby('user_id')
gp.apply(lambda x: x[x['start_time'] == x['start_time'].max()]).reset_index(drop=True)

Out[66]:
   user_id  start_time  A  B  C
0        1          45  d  e  f
1        1          45  g  g  i
2        2          58  j  k  l
3        2          58  p  q  r
4        3           2  s  t  u

如果我们没有调用 reset_index,你会得到重复的值:

In [67]:

gp.apply(lambda x: x[x['start_time'] == x['start_time'].max()])
Out[67]:
           user_id  start_time  A  B  C
user_id                                
1       1        1          45  d  e  f
        2        1          45  g  g  i
2       3        2          58  j  k  l
        5        2          58  p  q  r
3       6        3           2  s  t  u

内部布尔条件在多索引上生成一个布尔掩码,然后需要将其传递给 lambda 以生成上述内容:

In [68]:

gp.apply(lambda x: x['start_time'] == x['start_time'].max())
Out[68]:
user_id   
1        0    False
         1     True
         2     True
2        3     True
         4    False
         5     True
3        6     True
Name: start_time, dtype: bool

【讨论】:

  • 在更大的数据集上,运行时间为 790 毫秒,而 ajcr 和 Primer 的解决方案为 1345 毫秒。 (在我看来,它们都是正确的。)
【解决方案2】:

您也可以这样做:

df[df.start_time == df.groupby('user_id')['start_time'].transform(max)]

产量:

   user_id  start_time  A  B  C
1        1          45  d  e  f
2        1          45  g  h  i
3        2          58  j  k  l
5        2          58  p  q  r
6        3           2  s  t  u

【讨论】:

    猜你喜欢
    • 2018-10-31
    • 1970-01-01
    • 2020-04-27
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    • 2017-05-16
    • 1970-01-01
    • 2015-03-29
    相关资源
    最近更新 更多