2017-09-17 106 views
0

我有一個從不同長度的列表中創建的陣列。我不知道列表的長度,因此我使用列表而不是數組。轉換不同尺寸的陣列中的陣列到結構化陣列

下面是這個問題的目的,可重複碼:

a = [] 

for i in np.arange(5): 
    a += [np.random.rand(np.random.randint(1,6))] 

a = np.array(a) 

有沒有更有效的方式,比下面這個數組轉換成與行具有相同的大小與一個結構良好的陣列NaN的?

max_len_of_array = 0 
for aa in a: 
    len_of_array = aa.shape[0] 
    if len_of_array > max_len_of_array: 
     max_len_of_array = len_of_array 
max_len_of_array 

n = a.shape[0] 

A = np.zeros((n, max_len_of_array)) * np.nan 
for i, aa in enumerate(zip(a)): 
    A[i][:aa[0].shape[0]] = aa[0] 

A 
+1

你能保持max_len_of_array的'軌道'當你填寫原始列表時?否則你的方法似乎合理。 – nalyd88

+0

@ nalyd88是的,這是可能的,但我創造了大約10個這樣的數組。我想我可以爲'max_len_of_array'使用一個數組。 – user10853

+0

@DYZ我不明白這與我的問題有何關係。請澄清,如果你這樣做。 – user10853

回答

3

這裏是你的代碼的速度稍快的版本:

def alt(a): 
    A = np.full((len(a), max(map(len, a))), np.nan) 
    for i, aa in enumerate(a): 
     A[i, :len(aa)] = aa 
    return A 

的for循環是不可避免的。鑑於a是一個Python列表,周圍有必要通過在列表中的項目進行迭代沒有得到。有時循環可以隱藏(電話背後maxmap例如),但速度明智的,他們基本上等同於Python的循環。


下面是使用a與最終形狀(100, 100)基準:

In [197]: %timeit orig(a) 
10000 loops, best of 3: 125 µs per loop 

In [198]: %timeit alt(a) 
10000 loops, best of 3: 84.1 µs per loop 

In [199]: %timeit using_pandas(a) 
100 loops, best of 3: 4.8 ms per loop 

這是用來爲基準設置:

import numpy as np 
import pandas as pd 

def make_array(h, w): 
    a = [] 
    for i in np.arange(h): 
     a += [np.random.rand(np.random.randint(1,w+1))] 
    a = np.array(a) 
    return a 

def orig(a): 
    max_len_of_array = 0 

    for aa in a: 
     len_of_array = aa.shape[0] 
     if len_of_array > max_len_of_array: 
      max_len_of_array = len_of_array 

    n = a.shape[0] 

    A = np.zeros((n, max_len_of_array)) * np.nan 
    for i, aa in enumerate(zip(a)): 
     A[i][:aa[0].shape[0]] = aa[0] 

    return A 

def alt(a): 
    A = np.full((len(a), max(map(len, a))), np.nan) 
    for i, aa in enumerate(a): 
     A[i, :len(aa)] = aa 
    return A 

def using_pandas(a): 
    return pd.DataFrame.from_records(a).values 

a = make_array(100,100) 
0

我想你可以用大熊貓作爲一個一次性的解決方案,但它將會是非常低效的,好像一切熊貓:

pd.DataFrame(a)[0].apply(pd.Series).values 
#array([[ 0.28669545, 0.22080038, 0.32727194], 
#  [ 0.17892276,   nan,   nan], 
#  [ 0.26853548,   nan,   nan], 
#  [ 0.86460043, 0.78827094, 0.96660502], 
#  [ 0.41045599,   nan,   nan]]) 
+0

這似乎是另一種可能的解決方案,但你表明它是有效的,至少不會比循環更有效。 870微秒的熊貓與7.1微秒的循環。 – user10853