2017-09-17 107 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