![](/img/trans.png)
[英]How to iterate over column values for unique rows of a data frame with sorted, numerical index with duplicates in pandas?
[英]How to get rows in pandas data frame, with maximal values in a column and keep the original index?
我有一個熊貓數據框。 在第一列中,它可以多次具有相同的值(換句話說,第一列中的值不是唯一的)。
每當我在第一列中有多個包含相同值的行時,我只想留下第三列中具有最大值的行。 我幾乎找到了解決方案:
import pandas
ls = []
ls.append({'c1':'a', 'c2':'a', 'c3':1})
ls.append({'c1':'a', 'c2':'c', 'c3':3})
ls.append({'c1':'a', 'c2':'b', 'c3':2})
ls.append({'c1':'b', 'c2':'b', 'c3':10})
ls.append({'c1':'b', 'c2':'c', 'c3':12})
ls.append({'c1':'b', 'c2':'a', 'c3':7})
df = pandas.DataFrame(ls, columns=['c1','c2','c3'])
print df
print '--------------------'
print df.groupby('c1').apply(lambda df:df.irow(df['c3'].argmax()))
結果我得到:
c1 c2 c3
0 a a 1
1 a c 3
2 a b 2
3 b b 10
4 b c 12
5 b a 7
--------------------
c1 c2 c3
c1
a a c 3
b b c 12
我的問題是,我不想讓c1
作為索引。 我想要的是:
c1 c2 c3
1 a c 3
4 b c 12
當調用df.groupby(...).apply(foo)
, foo
返回的對象類型會影響結果融合在一起的方式。
如果返回一個Series,則Series的索引將成為最終結果的列,groupby鍵將成為索引(有點令人費解)。
如果您返回一個DataFrame,最終結果使用DataFrame的索引作為索引值,並將DataFrame的列作為列(非常明智)。
因此,您可以通過將Series轉換為DataFrame來安排所需的輸出類型。
使用Pandas 0.13,您可以使用to_frame().T
方法:
def maxrow(x, col):
return x.loc[x[col].argmax()].to_frame().T
result = df.groupby('c1').apply(maxrow, 'c3')
result = result.reset_index(level=0, drop=True)
print(result)
產量
c1 c2 c3
1 a c 3
4 b c 12
在Pandas 0.12或更早版本中,相當於:
def maxrow(x, col):
ser = x.loc[x[col].idxmax()]
df = pd.DataFrame({ser.name: ser}).T
return df
順便說一句, behzad.nouri的聰明而優雅的解決方案對於小型DataFrame來說比我的快。 然而,該sort
將時間復雜度從O(n)
提升到O(n log n)
,因此當應用於更大的DataFrame時,它變得比上面顯示的to_frame
解決方案慢。
以下是我對它進行基准測試的方法:
import pandas as pd
import numpy as np
import timeit
def reset_df_first(df):
df2 = df.reset_index()
result = df2.groupby('c1').apply(lambda x: x.loc[x['c3'].idxmax()])
result.set_index(['index'], inplace=True)
return result
def maxrow(x, col):
result = x.loc[x[col].argmax()].to_frame().T
return result
def using_to_frame(df):
result = df.groupby('c1').apply(maxrow, 'c3')
result.reset_index(level=0, drop=True, inplace=True)
return result
def using_sort(df):
return df.sort('c3').groupby('c1', as_index=False).tail(1)
for N in (100, 1000, 2000):
df = pd.DataFrame({'c1': {0: 'a', 1: 'a', 2: 'a', 3: 'b', 4: 'b', 5: 'b'},
'c2': {0: 'a', 1: 'c', 2: 'b', 3: 'b', 4: 'c', 5: 'a'},
'c3': {0: 1, 1: 3, 2: 2, 3: 10, 4: 12, 5: 7}})
df = pd.concat([df]*N)
df.reset_index(inplace=True, drop=True)
timing = dict()
for func in (reset_df_first, using_to_frame, using_sort):
timing[func] = timeit.timeit('m.{}(m.df)'.format(func.__name__),
'import __main__ as m ',
number=10)
print('For N = {}'.format(N))
for func in sorted(timing, key=timing.get):
print('{:<20}: {:<0.3g}'.format(func.__name__, timing[func]))
print
產量
For N = 100
using_sort : 0.018
using_to_frame : 0.0265
reset_df_first : 0.0303
For N = 1000
using_to_frame : 0.0358 \
using_sort : 0.036 / this is roughly where the two methods cross over in terms of performance
reset_df_first : 0.0432
For N = 2000
using_to_frame : 0.0457
reset_df_first : 0.0523
using_sort : 0.0569
( reset_df_first
是我嘗試的另一種可能性。)
試試這個:
df.sort('c3').groupby('c1', as_index=False).tail(1)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.