pandas - 获取由另一列索引的特定列的最新值(获取由另一列索引的特定列的最大值)

enr*_*shi 17 python pandas

我有以下数据帧:

   obj_id   data_date   value
0  4        2011-11-01  59500    
1  2        2011-10-01  35200 
2  4        2010-07-31  24860   
3  1        2009-07-28  15860
4  2        2008-10-15  200200
Run Code Online (Sandbox Code Playgroud)

我想得到这些数据的一个子集,这样我每个都只有最新的(最大的'data_date')数据.'value''obj_id'

我已经破解了一个解决方案,但感觉很脏.我想知道是否有人有更好的方法.我敢肯定我必须错过一些通过熊猫这么简单的方法.

我的方法主要是分组,排序,检索和重组,如下所示:

row_arr = []
for grp, grp_df in df.groupby('obj_id'):
    row_arr.append(dfg.sort('data_date', ascending = False)[:1].values[0])

df_new = DataFrame(row_arr, columns = ('obj_id', 'data_date', 'value'))
Run Code Online (Sandbox Code Playgroud)

小智 14

这是另一种可能的解决方案 我相信这是最快的.

df.loc[df.groupby('obj_id').data_date.idxmax(),:]
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的方法,在这个和其他环境中对我有用. (2认同)

the*_*ed1 11

如果"obj_id"的数量非常高,您将需要对整个数据帧进行排序,然后删除重复项以获取最后一个元素.

sorted = df.sort_index(by='data_date')
result = sorted.drop_duplicates('obj_id', keep='last').values
Run Code Online (Sandbox Code Playgroud)

这应该更快(抱歉,我没有测试它),因为您不必执行自定义agg功能,当有大量键时速度很慢.您可能认为对整个数据帧进行排序更糟糕,但实际上在python中排序很快且本机循环很慢.

  • 在 2022 年发现这一点,您现在需要根据 @Tamelise 的答案使用 `sort_values` 而不是 `sort_index` (2认同)

小智 5

我喜欢crewbum的答案,可能这更快(抱歉,还没有测试过,但我避免对所有内容进行排序):

df.groupby('obj_id').agg(lambda df: df.values[df['data_date'].values.argmax()])
Run Code Online (Sandbox Code Playgroud)

它使用 numpys“argmax”函数来查找出现最大值的行索引。


Gar*_*ett 2

groupby 对象上的aggregate () 方法可用于通过一个步骤从groupby 对象创建一个新的DataFrame。(不过,我不知道有更干净的方法来提取 DataFrame 的第一行/最后一行。)

In [12]: df.groupby('obj_id').agg(lambda df: df.sort('data_date')[-1:].values[0])
Out[12]: 
         data_date  value
obj_id                   
1       2009-07-28  15860
2       2011-10-01  35200
4       2011-11-01  59500
Run Code Online (Sandbox Code Playgroud)

您还可以对各个列执行聚合,在这种情况下,聚合函数适用于 Series 对象。

In [25]: df.groupby('obj_id')['value'].agg({'diff': lambda s: s.max() - s.min()})
Out[25]: 
          diff
obj_id        
1            0
2       165000
4        34640
Run Code Online (Sandbox Code Playgroud)