将不同大小的数组数组转换为结构化数组

时间:2017-09-17 23:42:55

标签: python numpy

我有一个从不同长度的列表创建的数组。我事先不知道列表的长度,这就是我使用列表而不是数组的原因。

以下是针对此问题的可重现代码:

a = []

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

a = np.array(a)

将这个数组转换为结构良好的数组,其行与NaNs的大小相同,是否有更有效的方法?

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

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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]])