2016-09-23 41 views
0

我有numpy的陣列下面:獲得在不等的行長度的numpy的陣列所需的元件,而不使用用於循環

array([['apple','banana','orange'], 
    ['car','bike','train','ship','plane','scooter'], 
    ['red','purple']], dtype=object) 

陣列中的各行長度不相等的,我想獲得的最後一個元素每行。我可以通過運行一個for循環來獲得這個,但我想可能有更直接的方法來做到這一點。我最接近的(錯誤的解決方案)是arr [:] [ - 1],它給了我最後一行元素和arr [np.arange(len(arr)), - 1],它引發了一個'IndexError'錯誤。

我所需的輸出是:

array([['orange','scooter','purple']], dtype=object) 

我會明白任何指導。謝謝。

回答

1

使用熊貓:

In [87]: a 
Out[87]: array([['apple', 'banana', 'orange'], ['car', 'bike', 'train', 'ship', 'plane', 'scooter'], ['red', 'purple']], dtype=object) 

In [88]: df = pd.DataFrame(a) 

In [93]: df 
Out[93]: 
              0 
0     [apple, banana, orange] 
1 [car, bike, train, ship, plane, scooter] 
2        [red, purple] 

In [94]: df[0].str[-1] 
Out[94]: 
0  orange 
1 scooter 
2  purple 
Name: 0, dtype: object 

或作爲與NumPy陣列:

In [95]: df[0].str[-1].values 
Out[95]: array(['orange', 'scooter', 'purple'], dtype=object) 
+1

這個解決方案工作。我的原始數據是熊貓DF和我使用.str操作,但這種解決方案並沒有打動我。謝謝。熊貓本身就是這樣做的: arr ['0'] = arr ['0']。str.split()。str [-1] –

+1

'pandas'永遠不會失敗! ;) – Divakar

+0

@Divakar,只在那些比NumPy慢的情況下...;) – MaxU

0

使用循環理解:np.array([i[-1] for i in arr],dtype=object)可能只是一個高效,快捷的方式,特別是如果該列表是足夠長的時間。但既然你問了一個不糊塗的解決方案,這是一個使用np.concatenate得到一個平坦的版本,然後索引到它與每個列表的最後元素的選擇正確索引的方式 -

np.concatenate(arr)[np.cumsum(map(len,arr))-1] 

這裏有一個用map運算符,它看起來不像矢量化操作,但由於我們使用它來只獲取列表的長度,所以該部分在運行時不應該很重。所以,我想這是一個幾乎矢量化的方法。

採樣運行 -

In [166]: arr 
Out[166]: 
array([['apple', 'banana', 'orange'], 
     ['car', 'bike', 'train', 'ship', 'plane', 'scooter'], 
     ['red', 'purple']], dtype=object) 

In [167]: np.concatenate(arr)[np.cumsum(map(len,arr))-1] 
Out[167]: 
array(['orange', 'scooter', 'purple'], 
     dtype='|S7') 

請注意,如果我們想要一個對象數組D型,我們需要建立索引之前轉換爲這樣的D型:np.concatenate(arr).astype(object)

1

如果使用最快的目錄列表:

import numpy as np 
import random 

items = ['apple','banana','orange', 'car','bike','train','ship','plane','scooter', 'red','purple'] 
a = [random.sample(items, random.randint(2, 10)) for _ in range(1000)] 
b = np.array(a) 

%timeit [x[-1] for x in a] # 62.1 µs 
%timeit [x[-1] for x in b] # 75.9 µs 
f = np.frompyfunc(lambda x:x[-1], 1, 1) 
%timeit f(b) # 165 µs 

import cytoolz 
%timeit list(cytoolz.pluck(-1, a)) # 42.7 µs 
%timeit list(cytoolz.pluck(-1, b)) # 75.8 µs 

import pandas as pd 
s = pd.Series(a) 
%timeit s.str[-1] # 965 µs 

即使你有一個數據幀或系列的對象,就可以將其轉換爲一個列表第一:

%timeit s.tolist() #45.6 µs 
相關問題