我有以下数据框:
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
我想获取此数据的子集,以便我每个'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'))
答案 0 :(得分:14)
这是另一种可能的解决方案。我相信这是最快的。
df.loc[df.groupby('obj_id').data_date.idxmax(),:]
答案 1 :(得分:8)
如果“obj_id”的数量非常高,您将需要对整个数据帧进行排序,然后删除重复项以获取最后一个元素。
sorted = df.sort_index(by='data_date')
result = sorted.drop_duplicates('obj_id', take_last=True).values
这应该更快(抱歉,我没有测试它),因为您不必执行自定义agg功能,当有大量键时速度很慢。您可能认为对整个数据帧进行排序更糟糕,但实际上在python中排序很快且本机循环很慢。
答案 2 :(得分:4)
我喜欢船员的答案,可能这更快(对不起,还没有测试过这个,但我避免整理所有内容):
df.groupby('obj_id').agg(lambda df: df.values[df['data_date'].values.argmax()])
它使用numpys“argmax”函数来查找出现最大值的rowindex。
答案 3 :(得分:2)
groupby对象上的aggregate() method可用于在一个步骤中从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
您还可以对各个列执行聚合,在这种情况下,聚合函数可以在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
答案 4 :(得分:2)
更新thetainted1的答案,因为有些功能现在有未来的警告,正如tommy.carstensen所指出的那样。这对我有用:
sorted = df.sort_values(by='data_date')
result = sorted.drop_duplicates('obj_id', keep='last')
答案 5 :(得分:0)
我相信已找到一个更合适的解决方案,基于此线程中的解决方案。 然而,我使用数据框的apply函数而不是聚合。 它还返回一个与原始列相同的新数据帧。
df = pd.DataFrame({
'CARD_NO': ['000', '001', '002', '002', '001', '111'],
'DATE': ['2006-12-31 20:11:39','2006-12-27 20:11:53','2006-12-28 20:12:11','2006-12-28 20:12:13','2008-12-27 20:11:53','2006-12-30 20:11:39']})
print df
df.groupby('CARD_NO').apply(lambda df:df['DATE'].values[df['DATE'].values.argmax()])
原创
CARD_NO DATE
0 000 2006-12-31 20:11:39
1 001 2006-12-27 20:11:53
2 002 2006-12-28 20:12:11
3 002 2006-12-28 20:12:13
4 001 2008-12-27 20:11:53
5 111 2006-12-30 20:11:39
返回的数据帧:
CARD_NO
000 2006-12-31 20:11:39
001 2008-12-27 20:11:53
002 2006-12-28 20:12:13
111 2006-12-30 20:11:39