2017-07-19 42 views
11

我有以下的(簡化)數據幀:返回n個最小通過使用列大熊貓指標

df = pd.DataFrame({'X': [1, 2, 3, 4, 5,6,7,8,9,10], 
'Y': [10,20,30,40,50,-10,-20,-30,-40,-50], 
'Z': [20,18,16,14,12,10,8,6,4,2]},index=list('ABCDEFGHIJ')) 

其中給出以下幾點:

X Y Z 
A 1 10 20 
B 2 20 18 
C 3 30 16 
D 4 40 14 
E 5 50 12 
F 6 -10 10 
G 7 -20 8 
H 8 -30 6 
I 9 -40 4 
J 10 -50 2 

我想創建一個新的數據框返回索引n列中最小的值。

所需的輸出(比如,3個最小值):

X Y Z 
0 A J J 
1 B I I 
2 C H H 

什麼是做到這一點的最好方法是什麼?

回答

10

更快numpy的解決方案與numpy.argsort

N = 3 
a = np.argsort(-df.values, axis=0)[-1:-1-N:-1] 
print (a) 
[[0 9 9] 
[1 8 8] 
[2 7 7]] 

b = pd.DataFrame(df.index[a], columns=df.columns) 
print (b) 
    X Y Z 
0 A J J 
1 B I I 
2 C H H 

時序

In [111]: %timeit (pd.DataFrame(df.index[np.argsort(-df.values, axis=0)[-1:-1-N:-1]], columns=df.columns)) 
159 µs ± 1.37 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each) 

In [112]: %timeit (df.apply(lambda x: pd.Series(x.nsmallest(N).index))) 
3.52 ms ± 49.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 
9

您可以使用applynsmallest

n = 3 
df.apply(lambda x: pd.Series(x.nsmallest(n).index)) 

# X Y Z 
#0 A J J 
#1 B I I 
#2 C H H 
0

首先,要排序的輸入dataframe per列,然後獲取每列的所有索引的列表,從這些索引創建一個數據幀,然後從結果數據幀中返回前n行。

def topN(df, n): 
#first, sort dataframe per column 
sort_x = df.sort_values(by = ['X'], ascending = True) 
sort_y = df.sort_values(by = ['Y'], ascending = True) 
sort_z = df.sort_values(by = ['Z'], ascending = True) 
#now get a list of the indices of each sorted df 
index_list_x = sort_x.index.values.tolist() 
index_list_y = sort_y.index.values.tolist() 
index_list_z = sort_z.index.values.tolist() 
#create dataframe from lists 
sorted_df = pd.DataFrame(
    {'sorted_x':index_list_x, 
    'sorted_y':index_list_y, 
    'sorted_z':index_list_z 
    }) 
#return the top n from the sorted dataframe 
return sorted_df.iloc[0:n] 

topN(df,3) 

返回:

X Y Z 
0 A J J 
1 B I I 
2 C H H