如何在Python中高效地扩展数组?

5
我的问题是如何高效地扩展一个数组,通过多次复制自身。我正在尝试将我的调查样本扩展到完整的数据集大小,通过将每个样本复制N次。N是分配给样本的影响因素。 所以我写了两个循环来完成这个任务(脚本如下)。它可以工作,但速度很慢。我的样本大小为20,000,并尝试将其扩展到3百万个全尺寸。有没有什么函数可以尝试?谢谢您的帮助!
lines = np.asarray(person.read().split('\n'))
df_array = np.asarray(lines[0].split(' '))
for j in range(1,len(lines)-1):
    subarray = np.asarray(lines[j].split(' '))
    factor = int(round(float(subarray[-1]),0))
    for i in range(1,factor):
        df_array = np.vstack((df_array, subarray))
print len(df_array)
3个回答

2

首先,您可以尝试使用numpy.loadtxt一次性加载所有数据。

然后,根据最后一列进行重复,使用numpy.repeat

>>> data = np.array([[1, 2, 3],
...                  [4, 5, 6]])
>>> np.repeat(data, data[:,-1], axis=0)
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3],
       [4, 5, 6],
       [4, 5, 6],
       [4, 5, 6],
       [4, 5, 6],
       [4, 5, 6],
       [4, 5, 6]])

最后,如果您需要将 data[:,-1] 四舍五入,请将其替换为 np.round(data[:,-1]).astype(int)


1
重复堆叠numpy数组并不是很高效,因为它们并没有像那样针对动态增长进行优化。每次使用vstack时,都会为该点处的数据大小分配一个全新的内存块。
最好使用列表,然后在最后构建数组,可能使用生成器来实现,例如:
def upsample(stream):
    for line in stream:
        rec = line.strip().split()
        factor = int(round(float(rec[-1]),0))
        for i in xrange(factor):
            yield rec

df_array = np.array(list(upsample(person)))

1
你要找的概念叫做“广播”。它允许你用一个(n-1)维数组的内容填充n维数组。
看看你的代码示例,你在循环中调用了np.vstack()。使用广播可以消除循环。
例如,如果你有一个包含n个元素的一维数组,
>>> n = 5 >>> df_array = np.arange(n) >>> df_array array([0, 1, 2, 3, 4])
你可以创建一个新的n x 10数组:
使用一行代码,你可以用较小的数组填充它。
>>> bigger_array = np.empty([10,n])
>>> bigger_array[:] = df_array
>>> bigger_array
array([[ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  1.,  2.,  3.,  4.]])
bigger_array[:] = df_array 注意:避免使用Python列表。它们比Numpy ndarray慢得多。

谢谢。如果我理解正确的话,您是说将 bigger_array[:] 应用于扩展小样本。在逐个扩展它们之后,我还需要将它们全部组合成一个大数据集。在那个阶段,不是扩展,而是组合...有没有比使用 np.vstack() 更有效的方法? - Angela Y
最有效的方法可能是使用 'np.empty()' 为您的最终数据集分配空间/内存,然后使用切片索引在其中加载数据和广播。这比在Python中使用循环本质上更快。 - timbo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接